From d1b8a69c6596cddbbed1230f38320c9dac4720ea Mon Sep 17 00:00:00 2001 From: Zaki Manian Date: Mon, 19 Dec 2022 15:36:43 -0500 Subject: [PATCH 01/18] feat: adding authz support for ICS-20 `MsgTransfer` (#2795) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ibc transfer authz work * add allowed address restriction for ibc transfer authz * expect error when transferring to not allowed address * feat: authz grants for ics-20 transfers Create an authz grant that resricts to transfers to specific addresses and channels. * convert IsAllPositive to Validate * add gas cost per interation * duplicated entry check * chore: scaffold custom IBC light client development guide (#2860) * chore: changing ibcprotocol.org to ibcprotocol.dev (#2884) * chore: update README to include link to IDA (#2887) * update README to reflect new website * pr comment * feat: Add genesis migrations for v6 to v7. The migration migrates the solo machine client state definition, removes all solo machine consensus states and removes the localhost client. (#2824) * refactor: simplify automatic migration code by using client keeper functions (#2864) * imp(api)!: remove legacy migrations required for upgrading from Stargate release line to ibc-go >= v1.x.x. (#2897) * chore: remove unnecessary file (#2898) * Update release-tracker.md * docs: v6 ICA migration docs improvements * e2e: changing default relayer tag to be v2.1.2 instead of main. (#2903) * refactor: simplify optional tendermint pruning migrations (#2862) * chore: add tmsdkeys to CODEOWNER for docs (#2904) * docs: add legacy docs for ICA * docs: added documentation for client state methods. (#2886) * docs: improvements to ICA docs * docs: move solomachine docs into the docs directory. (#2908) * deps: bump technote-space/get-diff-action from 6.1.1 to 6.1.2 (#2899) * deps: bump github.com/cosmos/cosmos-proto from 1.0.0-alpha8 to 1.0.0-beta.1 (#2870) * update README (#2910) * Update CHANGELOG.md * chore: update ibctest to latest commit (#2909) * update chainconfig * update to commit fixing broadcastTx * update to use SDK default cointype 118 * update so relayer tag isn't required * Fixing markdown link (#2924) * post v6.0.0 release chores (#2919) * docs: update integration docs to include light client registration. (#2905) * imp: Add `AssertEvents` which asserts events against expected event map. (#2829) * e2e: adding e2e upgrade test for ibc-go v7 (#2902) * add test for automatic migration of solomachine clientstate version * add clientID generation functions * update godoc * update sprintf message * e2e: update tags in e2e upgrade test * chore: use diffs to make registration more clear (#2927) * nit: fix typo in a comment * refactor: require light clients to set the initial client state and consensus state via the client state `Initialize` method (#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 * Update docs/ibc/light-clients/client-state.md Co-authored-by: Carlos Rodriguez * adding tests to lightclients * updating 02-client tests Co-authored-by: Charly Co-authored-by: Carlos Rodriguez * chore: add backports for v4.3.x and v6.1.x * update compatibility tests with new release branches (#2946) * update compatibility tests * compatibility tests for v4.3.x * adding tags to tests * Skip e2e if test matrix does not exist (#2949) Co-authored-by: Carlos Rodriguez Co-authored-by: Cian Hatton * fix(statemachine)!: check x/bank send enabled before escrowing fees * chore(deps): bump goreleaser/goreleaser-action from 3 to 4 (#2932) Bumps [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) from 3 to 4. - [Release notes](https://github.com/goreleaser/goreleaser-action/releases) - [Commits](https://github.com/goreleaser/goreleaser-action/compare/v3...v4) --- updated-dependencies: - dependency-name: goreleaser/goreleaser-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Carlos Rodriguez * chore(api)!: removing solomachine header sequence (#2941) * removing solomachine header sequence * removing commented out code in validate basic * chore(deps): bump bufbuild/buf-setup-action from 1.9.0 to 1.10.0 (#2933) * Resolve some code review comments Signed-off-by: dependabot[bot] Co-authored-by: jgo121 Co-authored-by: junkai121 <39806640+junkai121@users.noreply.github.com> Co-authored-by: Charly Co-authored-by: Cian Hatton Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> Co-authored-by: Carlos Rodriguez Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Anmol Co-authored-by: Charly Co-authored-by: Auridas F Co-authored-by: Damian Nolan --- .github/workflows/proto-registry.yml | 2 +- .github/workflows/release.yml | 2 +- docs/ibc/proto-docs.md | 54 ++ modules/apps/transfer/types/authz.pb.go | 694 ++++++++++++++++++ modules/apps/transfer/types/codec.go | 6 + modules/apps/transfer/types/errors.go | 1 + modules/apps/transfer/types/transfer_authz.go | 116 +++ .../transfer/types/transfer_authz_test.go | 86 +++ .../light-clients/06-solomachine/header.go | 6 +- .../06-solomachine/header_test.go | 15 - .../06-solomachine/solomachine.pb.go | 141 ++-- .../light-clients/06-solomachine/update.go | 10 +- .../06-solomachine/update_test.go | 11 - .../ibc/applications/transfer/v2/authz.proto | 30 + .../solomachine/v3/solomachine.proto | 25 +- testing/solomachine.go | 1 - 16 files changed, 1060 insertions(+), 140 deletions(-) create mode 100644 modules/apps/transfer/types/authz.pb.go create mode 100644 modules/apps/transfer/types/transfer_authz.go create mode 100644 modules/apps/transfer/types/transfer_authz_test.go create mode 100644 proto/ibc/applications/transfer/v2/authz.proto diff --git a/.github/workflows/proto-registry.yml b/.github/workflows/proto-registry.yml index 1aa89109785..aa617f57be1 100644 --- a/.github/workflows/proto-registry.yml +++ b/.github/workflows/proto-registry.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: bufbuild/buf-setup-action@v1.9.0 + - uses: bufbuild/buf-setup-action@v1.10.0 - uses: bufbuild/buf-push-action@v1 with: input: "proto" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6fe0111d8e0..def7fd287c7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -24,7 +24,7 @@ jobs: go-version: '1.18' - name: Release - uses: goreleaser/goreleaser-action@v3 + uses: goreleaser/goreleaser-action@v4 if: startsWith(github.ref, 'refs/tags/') with: version: latest diff --git a/docs/ibc/proto-docs.md b/docs/ibc/proto-docs.md index 91154efa20b..5ec2d594cf0 100644 --- a/docs/ibc/proto-docs.md +++ b/docs/ibc/proto-docs.md @@ -154,6 +154,10 @@ - [Msg](#ibc.applications.transfer.v1.Msg) +- [ibc/applications/transfer/v2/authz.proto](#ibc/applications/transfer/v2/authz.proto) + - [PortChannelAmount](#ibc.applications.transfer.v2.PortChannelAmount) + - [TransferAuthorization](#ibc.applications.transfer.v2.TransferAuthorization) + - [ibc/applications/transfer/v2/packet.proto](#ibc/applications/transfer/v2/packet.proto) - [FungibleTokenPacketData](#ibc.applications.transfer.v2.FungibleTokenPacketData) @@ -2296,6 +2300,56 @@ Msg defines the ibc/transfer Msg service. + +

Top

+ +## ibc/applications/transfer/v2/authz.proto + + + + + +### PortChannelAmount + + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `source_port` | [string](#string) | | the port on which the packet will be sent | +| `source_channel` | [string](#string) | | the channel by which the packet will be sent | +| `spend_limit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | spend limitation on the channel | +| `allowed_addresses` | [string](#string) | repeated | | + + + + + + + + +### TransferAuthorization +TransferAuthorization allows the grantee to spend up to spend_limit coins from +the granter's account for ibc transfer on a specific channel + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `allocations` | [PortChannelAmount](#ibc.applications.transfer.v2.PortChannelAmount) | repeated | port and channel amounts | + + + + + + + + + + + + + + +

Top

diff --git a/modules/apps/transfer/types/authz.pb.go b/modules/apps/transfer/types/authz.pb.go new file mode 100644 index 00000000000..db9a9e3dbc3 --- /dev/null +++ b/modules/apps/transfer/types/authz.pb.go @@ -0,0 +1,694 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: ibc/applications/transfer/v2/authz.proto + +package types + +import ( + fmt "fmt" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + _ "github.com/regen-network/cosmos-proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type PortChannelAmount struct { + // the port on which the packet will be sent + 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 + SourceChannel string `protobuf:"bytes,2,opt,name=source_channel,json=sourceChannel,proto3" json:"source_channel,omitempty" yaml:"source_channel"` + // spend limitation on the channel + SpendLimit github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,3,rep,name=spend_limit,json=spendLimit,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"spend_limit"` + // allowed addresses to be sent via transfer message + AllowedAddresses []string `protobuf:"bytes,4,rep,name=allowed_addresses,json=allowedAddresses,proto3" json:"allowed_addresses,omitempty"` +} + +func (m *PortChannelAmount) Reset() { *m = PortChannelAmount{} } +func (m *PortChannelAmount) String() string { return proto.CompactTextString(m) } +func (*PortChannelAmount) ProtoMessage() {} +func (*PortChannelAmount) Descriptor() ([]byte, []int) { + return fileDescriptor_c4c17169771443ae, []int{0} +} +func (m *PortChannelAmount) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PortChannelAmount) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PortChannelAmount.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PortChannelAmount) XXX_Merge(src proto.Message) { + xxx_messageInfo_PortChannelAmount.Merge(m, src) +} +func (m *PortChannelAmount) XXX_Size() int { + return m.Size() +} +func (m *PortChannelAmount) XXX_DiscardUnknown() { + xxx_messageInfo_PortChannelAmount.DiscardUnknown(m) +} + +var xxx_messageInfo_PortChannelAmount proto.InternalMessageInfo + +func (m *PortChannelAmount) GetSourcePort() string { + if m != nil { + return m.SourcePort + } + return "" +} + +func (m *PortChannelAmount) GetSourceChannel() string { + if m != nil { + return m.SourceChannel + } + return "" +} + +func (m *PortChannelAmount) GetSpendLimit() github_com_cosmos_cosmos_sdk_types.Coins { + if m != nil { + return m.SpendLimit + } + return nil +} + +func (m *PortChannelAmount) GetAllowedAddresses() []string { + if m != nil { + return m.AllowedAddresses + } + return nil +} + +// TransferAuthorization allows the grantee to spend up to spend_limit coins from +// the granter's account for ibc transfer on a specific channel +type TransferAuthorization struct { + // port and channel amounts + Allocations []PortChannelAmount `protobuf:"bytes,1,rep,name=allocations,proto3" json:"allocations"` +} + +func (m *TransferAuthorization) Reset() { *m = TransferAuthorization{} } +func (m *TransferAuthorization) String() string { return proto.CompactTextString(m) } +func (*TransferAuthorization) ProtoMessage() {} +func (*TransferAuthorization) Descriptor() ([]byte, []int) { + return fileDescriptor_c4c17169771443ae, []int{1} +} +func (m *TransferAuthorization) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TransferAuthorization) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TransferAuthorization.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *TransferAuthorization) XXX_Merge(src proto.Message) { + xxx_messageInfo_TransferAuthorization.Merge(m, src) +} +func (m *TransferAuthorization) XXX_Size() int { + return m.Size() +} +func (m *TransferAuthorization) XXX_DiscardUnknown() { + xxx_messageInfo_TransferAuthorization.DiscardUnknown(m) +} + +var xxx_messageInfo_TransferAuthorization proto.InternalMessageInfo + +func (m *TransferAuthorization) GetAllocations() []PortChannelAmount { + if m != nil { + return m.Allocations + } + return nil +} + +func init() { + proto.RegisterType((*PortChannelAmount)(nil), "ibc.applications.transfer.v2.PortChannelAmount") + proto.RegisterType((*TransferAuthorization)(nil), "ibc.applications.transfer.v2.TransferAuthorization") +} + +func init() { + proto.RegisterFile("ibc/applications/transfer/v2/authz.proto", fileDescriptor_c4c17169771443ae) +} + +var fileDescriptor_c4c17169771443ae = []byte{ + // 442 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x52, 0xc1, 0x6a, 0xdb, 0x30, + 0x18, 0x8e, 0x9b, 0x32, 0xa8, 0x42, 0xc7, 0x62, 0xd6, 0xe1, 0x94, 0xe1, 0x04, 0x9f, 0x0c, 0x23, + 0xd2, 0x9a, 0xc1, 0x0a, 0x3d, 0x2d, 0xe9, 0x75, 0x87, 0xcd, 0x0c, 0x06, 0xbb, 0x04, 0x59, 0xd6, + 0x12, 0x31, 0x5b, 0xbf, 0x91, 0xe4, 0x8c, 0xf6, 0xba, 0x17, 0xd8, 0x6b, 0x6c, 0xe7, 0x3d, 0x44, + 0x8f, 0x65, 0xa7, 0x9d, 0xb2, 0x91, 0xbc, 0x41, 0x9f, 0x60, 0x58, 0x52, 0x21, 0xa5, 0xd0, 0x93, + 0xad, 0xff, 0xfb, 0xfe, 0x4f, 0xfa, 0xbf, 0xef, 0x47, 0xa9, 0xc8, 0x19, 0xa1, 0x75, 0x5d, 0x0a, + 0x46, 0x8d, 0x00, 0xa9, 0x89, 0x51, 0x54, 0xea, 0xcf, 0x5c, 0x91, 0xd5, 0x84, 0xd0, 0xc6, 0x2c, + 0x2f, 0x71, 0xad, 0xc0, 0x40, 0xf8, 0x5c, 0xe4, 0x0c, 0xef, 0x32, 0xf1, 0x2d, 0x13, 0xaf, 0x26, + 0xc7, 0x03, 0x06, 0xba, 0x02, 0x3d, 0xb7, 0x5c, 0xe2, 0x0e, 0xae, 0xf1, 0xf8, 0xe9, 0x02, 0x16, + 0xe0, 0xea, 0xed, 0x9f, 0xaf, 0xc6, 0x8e, 0x43, 0x72, 0xaa, 0x39, 0x59, 0x9d, 0xe4, 0xdc, 0xd0, + 0x13, 0xc2, 0x40, 0x48, 0x87, 0x27, 0x3f, 0xf6, 0x50, 0xff, 0x1d, 0x28, 0x73, 0xbe, 0xa4, 0x52, + 0xf2, 0x72, 0x5a, 0x41, 0x23, 0x4d, 0x78, 0x8a, 0x7a, 0x1a, 0x1a, 0xc5, 0xf8, 0xbc, 0x06, 0x65, + 0xa2, 0x60, 0x14, 0xa4, 0x07, 0xb3, 0x67, 0x37, 0xeb, 0x61, 0x78, 0x41, 0xab, 0xf2, 0x2c, 0xd9, + 0x01, 0x93, 0x0c, 0xb9, 0x53, 0xab, 0x12, 0xbe, 0x41, 0x8f, 0x3d, 0xc6, 0x9c, 0x60, 0xb4, 0x67, + 0x7b, 0x07, 0x37, 0xeb, 0xe1, 0xd1, 0x9d, 0x5e, 0x8f, 0x27, 0xd9, 0xa1, 0x2b, 0xf8, 0x07, 0x84, + 0x25, 0xea, 0xe9, 0x9a, 0xcb, 0x62, 0x5e, 0x8a, 0x4a, 0x98, 0xa8, 0x3b, 0xea, 0xa6, 0xbd, 0xc9, + 0x00, 0xfb, 0x51, 0xdb, 0x31, 0xb0, 0x1f, 0x03, 0x9f, 0x83, 0x90, 0xb3, 0x97, 0x57, 0xeb, 0x61, + 0xe7, 0xe7, 0xdf, 0x61, 0xba, 0x10, 0x66, 0xd9, 0xe4, 0x98, 0x41, 0xe5, 0x7d, 0xf1, 0x9f, 0xb1, + 0x2e, 0xbe, 0x10, 0x73, 0x51, 0x73, 0x6d, 0x1b, 0x74, 0x86, 0xac, 0xfe, 0xdb, 0x56, 0x3e, 0x7c, + 0x81, 0xfa, 0xb4, 0x2c, 0xe1, 0x2b, 0x2f, 0xe6, 0xb4, 0x28, 0x14, 0xd7, 0x9a, 0xeb, 0x68, 0x7f, + 0xd4, 0x4d, 0x0f, 0xb2, 0x27, 0x1e, 0x98, 0xde, 0xd6, 0x93, 0x6f, 0x01, 0x3a, 0xfa, 0xe0, 0xc3, + 0x98, 0x36, 0x66, 0x09, 0x4a, 0x5c, 0xda, 0x8c, 0xc2, 0x8f, 0xa8, 0xd7, 0xb2, 0x7d, 0x62, 0x51, + 0x60, 0x1f, 0x4d, 0xf0, 0x43, 0x51, 0xe2, 0x7b, 0xae, 0xcf, 0xf6, 0xdb, 0x51, 0xb2, 0x5d, 0xa5, + 0xb3, 0xfe, 0xef, 0x5f, 0xe3, 0xc3, 0x3b, 0x77, 0xcd, 0xde, 0x5f, 0x6d, 0xe2, 0xe0, 0x7a, 0x13, + 0x07, 0xff, 0x36, 0x71, 0xf0, 0x7d, 0x1b, 0x77, 0xae, 0xb7, 0x71, 0xe7, 0xcf, 0x36, 0xee, 0x7c, + 0x3a, 0xbd, 0x6f, 0x81, 0xc8, 0xd9, 0x78, 0x01, 0x64, 0xf5, 0x9a, 0x54, 0x50, 0x34, 0x25, 0xd7, + 0xed, 0x12, 0xee, 0x2c, 0x9f, 0xf5, 0x25, 0x7f, 0x64, 0x77, 0xe1, 0xd5, 0xff, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x1b, 0x30, 0xdf, 0x96, 0xa6, 0x02, 0x00, 0x00, +} + +func (m *PortChannelAmount) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PortChannelAmount) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PortChannelAmount) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.AllowedAddresses) > 0 { + for iNdEx := len(m.AllowedAddresses) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.AllowedAddresses[iNdEx]) + copy(dAtA[i:], m.AllowedAddresses[iNdEx]) + i = encodeVarintAuthz(dAtA, i, uint64(len(m.AllowedAddresses[iNdEx]))) + i-- + dAtA[i] = 0x22 + } + } + if len(m.SpendLimit) > 0 { + for iNdEx := len(m.SpendLimit) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.SpendLimit[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintAuthz(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if len(m.SourceChannel) > 0 { + i -= len(m.SourceChannel) + copy(dAtA[i:], m.SourceChannel) + i = encodeVarintAuthz(dAtA, i, uint64(len(m.SourceChannel))) + i-- + dAtA[i] = 0x12 + } + if len(m.SourcePort) > 0 { + i -= len(m.SourcePort) + copy(dAtA[i:], m.SourcePort) + i = encodeVarintAuthz(dAtA, i, uint64(len(m.SourcePort))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *TransferAuthorization) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TransferAuthorization) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TransferAuthorization) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Allocations) > 0 { + for iNdEx := len(m.Allocations) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Allocations[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintAuthz(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func encodeVarintAuthz(dAtA []byte, offset int, v uint64) int { + offset -= sovAuthz(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *PortChannelAmount) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.SourcePort) + if l > 0 { + n += 1 + l + sovAuthz(uint64(l)) + } + l = len(m.SourceChannel) + if l > 0 { + n += 1 + l + sovAuthz(uint64(l)) + } + if len(m.SpendLimit) > 0 { + for _, e := range m.SpendLimit { + l = e.Size() + n += 1 + l + sovAuthz(uint64(l)) + } + } + if len(m.AllowedAddresses) > 0 { + for _, s := range m.AllowedAddresses { + l = len(s) + n += 1 + l + sovAuthz(uint64(l)) + } + } + return n +} + +func (m *TransferAuthorization) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Allocations) > 0 { + for _, e := range m.Allocations { + l = e.Size() + n += 1 + l + sovAuthz(uint64(l)) + } + } + return n +} + +func sovAuthz(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozAuthz(x uint64) (n int) { + return sovAuthz(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *PortChannelAmount) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthz + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PortChannelAmount: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PortChannelAmount: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SourcePort", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthz + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthAuthz + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthAuthz + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SourcePort = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SourceChannel", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthz + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthAuthz + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthAuthz + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SourceChannel = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SpendLimit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthz + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthAuthz + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthAuthz + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SpendLimit = append(m.SpendLimit, types.Coin{}) + if err := m.SpendLimit[len(m.SpendLimit)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowedAddresses", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthz + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthAuthz + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthAuthz + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AllowedAddresses = append(m.AllowedAddresses, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipAuthz(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthAuthz + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TransferAuthorization) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthz + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TransferAuthorization: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TransferAuthorization: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Allocations", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthz + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthAuthz + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthAuthz + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Allocations = append(m.Allocations, PortChannelAmount{}) + if err := m.Allocations[len(m.Allocations)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipAuthz(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthAuthz + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipAuthz(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowAuthz + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowAuthz + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowAuthz + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthAuthz + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupAuthz + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthAuthz + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthAuthz = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowAuthz = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupAuthz = fmt.Errorf("proto: unexpected end of group") +) diff --git a/modules/apps/transfer/types/codec.go b/modules/apps/transfer/types/codec.go index 3067cf8dc9d..aef9c1635b9 100644 --- a/modules/apps/transfer/types/codec.go +++ b/modules/apps/transfer/types/codec.go @@ -7,6 +7,7 @@ import ( codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/msgservice" + "github.com/cosmos/cosmos-sdk/x/authz" "github.com/gogo/protobuf/jsonpb" "github.com/gogo/protobuf/proto" ) @@ -22,6 +23,11 @@ func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { func RegisterInterfaces(registry codectypes.InterfaceRegistry) { registry.RegisterImplementations((*sdk.Msg)(nil), &MsgTransfer{}) + registry.RegisterImplementations( + (*authz.Authorization)(nil), + &TransferAuthorization{}, + ) + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) } diff --git a/modules/apps/transfer/types/errors.go b/modules/apps/transfer/types/errors.go index 0f0cb7c42a4..1dcbec14431 100644 --- a/modules/apps/transfer/types/errors.go +++ b/modules/apps/transfer/types/errors.go @@ -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") ) diff --git a/modules/apps/transfer/types/transfer_authz.go b/modules/apps/transfer/types/transfer_authz.go new file mode 100644 index 00000000000..bcf6e3ebb27 --- /dev/null +++ b/modules/apps/transfer/types/transfer_authz.go @@ -0,0 +1,116 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/x/authz" + host "github.com/cosmos/ibc-go/v6/modules/core/24-host" + + "golang.org/x/exp/slices" +) + +const gasCostPerIteration = uint64(10) + +var ( + _ authz.Authorization = &TransferAuthorization{} +) + +// NewTransferAuthorization creates a new TransferAuthorization object. +func NewTransferAuthorization(sourcePorts, sourceChannels []string, spendLimits []sdk.Coins, allowedAddrs [][]string) *TransferAuthorization { + allocations := []PortChannelAmount{} + for index := range sourcePorts { + allocations = append(allocations, PortChannelAmount{ + SourcePort: sourcePorts[index], + SourceChannel: sourceChannels[index], + SpendLimit: spendLimits[index], + AllowedAddresses: allowedAddrs[index], + }) + } + return &TransferAuthorization{ + Allocations: allocations, + } +} + +// MsgTypeURL implements Authorization.MsgTypeURL. +func (a TransferAuthorization) MsgTypeURL() string { + return sdk.MsgTypeURL(&MsgTransfer{}) +} + +func IsAllowedAddress(ctx sdk.Context, receiver string, allowedAddrs []string) bool { + for _, addr := range allowedAddrs { + ctx.GasMeter().ConsumeGas(gasCostPerIteration, "transfer authorization") + if addr == receiver { + return true + } + } + return false +} + +// Accept implements Authorization.Accept. +func (a TransferAuthorization) Accept(ctx sdk.Context, msg sdk.Msg) (authz.AcceptResponse, error) { + msgTransfer, ok := msg.(*MsgTransfer) + if !ok { + return authz.AcceptResponse{}, sdkerrors.Wrap(sdkerrors.ErrInvalidType, "type mismatch") + } + + for index, allocation := range a.Allocations { + if allocation.SourceChannel == msgTransfer.SourceChannel && allocation.SourcePort == msgTransfer.SourcePort { + limitLeft, isNegative := allocation.SpendLimit.SafeSub(msgTransfer.Token) + if isNegative { + return authz.AcceptResponse{}, sdkerrors.ErrInsufficientFunds.Wrapf("requested amount is more than spend limit") + } + + if !IsAllowedAddress(ctx, msgTransfer.Receiver, allocation.AllowedAddresses) { + return authz.AcceptResponse{}, sdkerrors.ErrInvalidAddress.Wrapf("not allowed address for transfer") + } + + if limitLeft.IsZero() { + a.Allocations = slices.Delete(a.Allocations, index, index+1) + if len(a.Allocations) == 0 { + return authz.AcceptResponse{Accept: true, Delete: true}, nil + } + return authz.AcceptResponse{Accept: true, Delete: false, Updated: &TransferAuthorization{ + Allocations: a.Allocations, + }}, nil + } + a.Allocations[index] = PortChannelAmount{ + SourcePort: allocation.SourcePort, + SourceChannel: allocation.SourceChannel, + SpendLimit: limitLeft, + AllowedAddresses: allocation.AllowedAddresses, + } + + return authz.AcceptResponse{Accept: true, Delete: false, Updated: &TransferAuthorization{ + Allocations: a.Allocations, + }}, nil + } + } + return authz.AcceptResponse{}, sdkerrors.ErrNotFound.Wrapf("requested port and channel allocation does not exist") +} + +// ValidateBasic implements Authorization.ValidateBasic. +func (a TransferAuthorization) ValidateBasic() error { + for _, allocation := range a.Allocations { + if allocation.SpendLimit == nil { + return sdkerrors.ErrInvalidCoins.Wrap("spend limit cannot be nil") + } + if err := allocation.SpendLimit.Validate(); err != nil { + return sdkerrors.ErrInvalidCoins.Wrapf(err.Error()) + } + if err := host.PortIdentifierValidator(allocation.SourcePort); err != nil { + return sdkerrors.Wrap(err, "invalid source port ID") + } + if err := host.ChannelIdentifierValidator(allocation.SourceChannel); err != nil { + return sdkerrors.Wrap(err, "invalid source channel ID") + } + + found := make(map[string]bool, 0) + for i := 0; i < len(allocation.AllowedAddresses); i++ { + if found[allocation.AllowedAddresses[i]] { + return ErrDuplicateEntry + } + found[allocation.AllowedAddresses[i]] = true + } + } + return nil +} diff --git a/modules/apps/transfer/types/transfer_authz_test.go b/modules/apps/transfer/types/transfer_authz_test.go new file mode 100644 index 00000000000..022188e747c --- /dev/null +++ b/modules/apps/transfer/types/transfer_authz_test.go @@ -0,0 +1,86 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/require" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + "github.com/cosmos/cosmos-sdk/simapp" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var ( + sourcePort = "port" + sourceChannel = "channel-100" + sourcePort2 = "port2" + sourceChannel2 = "channel-101" + coins1000 = sdk.Coins{sdk.NewCoin("stake", sdk.NewInt(1000))} + coins500 = sdk.Coins{sdk.NewCoin("stake", sdk.NewInt(500))} + coin1000 = sdk.NewCoin("stake", sdk.NewInt(1000)) + coin500 = sdk.NewCoin("stake", sdk.NewInt(500)) + fromAddr = sdk.AccAddress("_____from _____") + toAddr = sdk.AccAddress("_______to________") +) + +func TestTransferAuthorization(t *testing.T) { + app := simapp.Setup(t, false) + ctx := app.BaseApp.NewContext(false, tmproto.Header{}) + authorization := NewTransferAuthorization([]string{sourcePort}, []string{sourceChannel}, []sdk.Coins{coins1000}, [][]string{{toAddr.String()}}) + + t.Log("verify authorization returns valid method name") + require.Equal(t, authorization.MsgTypeURL(), "/ibc.applications.transfer.v1.MsgTransfer") + require.NoError(t, authorization.ValidateBasic()) + transfer := NewMsgTransfer(sourcePort, sourceChannel, coin1000, fromAddr.String(), toAddr.String(), timeoutHeight, 0) + require.NoError(t, authorization.ValidateBasic()) + + t.Log("verify updated authorization returns nil") + resp, err := authorization.Accept(ctx, transfer) + require.NoError(t, err) + require.True(t, resp.Delete) + require.Nil(t, resp.Updated) + + t.Log("verify updated authorization returns remaining spent limit") + authorization = NewTransferAuthorization([]string{sourcePort}, []string{sourceChannel}, []sdk.Coins{coins1000}, [][]string{{toAddr.String()}}) + require.Equal(t, authorization.MsgTypeURL(), "/ibc.applications.transfer.v1.MsgTransfer") + require.NoError(t, authorization.ValidateBasic()) + transfer = NewMsgTransfer(sourcePort, sourceChannel, coin500, fromAddr.String(), toAddr.String(), timeoutHeight, 0) + require.NoError(t, authorization.ValidateBasic()) + resp, err = authorization.Accept(ctx, transfer) + require.NoError(t, err) + require.False(t, resp.Delete) + require.NotNil(t, resp.Updated) + sendAuth := NewTransferAuthorization([]string{sourcePort}, []string{sourceChannel}, []sdk.Coins{coins500}, [][]string{{toAddr.String()}}) + require.Equal(t, sendAuth.String(), resp.Updated.String()) + + t.Log("expect updated authorization nil after spending remaining amount") + resp, err = resp.Updated.Accept(ctx, transfer) + require.NoError(t, err) + require.True(t, resp.Delete) + require.Nil(t, resp.Updated) + + t.Log("expect error when spend limit for specific port and channel is not set") + authorization = NewTransferAuthorization([]string{sourcePort}, []string{sourceChannel}, []sdk.Coins{coins1000}, [][]string{{toAddr.String()}}) + transfer = NewMsgTransfer(sourcePort2, sourceChannel2, coin500, fromAddr.String(), toAddr.String(), timeoutHeight, 0) + _, err = authorization.Accept(ctx, transfer) + require.Error(t, err) + + t.Log("expect removing only 1 allocation if spend limit is finalized for the port") + authorization = NewTransferAuthorization( + []string{sourcePort, sourcePort2}, + []string{sourceChannel, sourceChannel2}, + []sdk.Coins{coins1000, coins1000}, + [][]string{{toAddr.String()}, {toAddr.String()}}) + transfer = NewMsgTransfer(sourcePort, sourceChannel, coin1000, fromAddr.String(), toAddr.String(), timeoutHeight, 0) + resp, err = authorization.Accept(ctx, transfer) + require.NoError(t, err) + require.NotNil(t, resp.Updated) + require.Equal(t, resp.Updated, NewTransferAuthorization([]string{sourcePort2}, []string{sourceChannel2}, []sdk.Coins{coins1000}, [][]string{{toAddr.String()}})) + require.False(t, resp.Delete) + + t.Log("expect error when transferring to not allowed address") + authorization = NewTransferAuthorization([]string{sourcePort}, []string{sourceChannel}, []sdk.Coins{coins1000}, [][]string{{fromAddr.String()}}) + transfer = NewMsgTransfer(sourcePort, sourceChannel, coin500, fromAddr.String(), toAddr.String(), timeoutHeight, 0) + _, err = authorization.Accept(ctx, transfer) + require.Error(t, err) +} diff --git a/modules/light-clients/06-solomachine/header.go b/modules/light-clients/06-solomachine/header.go index 633c25425bc..382eddfe34e 100644 --- a/modules/light-clients/06-solomachine/header.go +++ b/modules/light-clients/06-solomachine/header.go @@ -36,13 +36,9 @@ func (h Header) GetPubKey() (cryptotypes.PubKey, error) { return publicKey, nil } -// ValidateBasic ensures that the sequence, signature and public key have all +// ValidateBasic ensures that the timestamp, signature and public key have all // been initialized. func (h Header) ValidateBasic() error { - if h.Sequence == 0 { - return sdkerrors.Wrap(clienttypes.ErrInvalidHeader, "sequence number cannot be zero") - } - if h.Timestamp == 0 { return sdkerrors.Wrap(clienttypes.ErrInvalidHeader, "timestamp cannot be zero") } diff --git a/modules/light-clients/06-solomachine/header_test.go b/modules/light-clients/06-solomachine/header_test.go index 7d752d88a8c..4aa9e506711 100644 --- a/modules/light-clients/06-solomachine/header_test.go +++ b/modules/light-clients/06-solomachine/header_test.go @@ -22,21 +22,9 @@ func (suite *SoloMachineTestSuite) TestHeaderValidateBasic() { header, true, }, - { - "sequence is zero", - &solomachine.Header{ - Sequence: 0, - Timestamp: header.Timestamp, - Signature: header.Signature, - NewPublicKey: header.NewPublicKey, - NewDiversifier: header.NewDiversifier, - }, - false, - }, { "timestamp is zero", &solomachine.Header{ - Sequence: header.Sequence, Timestamp: 0, Signature: header.Signature, NewPublicKey: header.NewPublicKey, @@ -47,7 +35,6 @@ func (suite *SoloMachineTestSuite) TestHeaderValidateBasic() { { "signature is empty", &solomachine.Header{ - Sequence: header.Sequence, Timestamp: header.Timestamp, Signature: []byte{}, NewPublicKey: header.NewPublicKey, @@ -58,7 +45,6 @@ func (suite *SoloMachineTestSuite) TestHeaderValidateBasic() { { "diversifier contains only spaces", &solomachine.Header{ - Sequence: header.Sequence, Timestamp: header.Timestamp, Signature: header.Signature, NewPublicKey: header.NewPublicKey, @@ -69,7 +55,6 @@ func (suite *SoloMachineTestSuite) TestHeaderValidateBasic() { { "public key is nil", &solomachine.Header{ - Sequence: header.Sequence, Timestamp: header.Timestamp, Signature: header.Signature, NewPublicKey: nil, diff --git a/modules/light-clients/06-solomachine/solomachine.pb.go b/modules/light-clients/06-solomachine/solomachine.pb.go index 7d2f64ed5ce..a53e2f0380f 100644 --- a/modules/light-clients/06-solomachine/solomachine.pb.go +++ b/modules/light-clients/06-solomachine/solomachine.pb.go @@ -115,12 +115,10 @@ var xxx_messageInfo_ConsensusState proto.InternalMessageInfo // Header defines a solo machine consensus header type Header struct { - // sequence to update solo machine public key at - Sequence uint64 `protobuf:"varint,1,opt,name=sequence,proto3" json:"sequence,omitempty"` - Timestamp uint64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - Signature []byte `protobuf:"bytes,3,opt,name=signature,proto3" json:"signature,omitempty"` - NewPublicKey *types.Any `protobuf:"bytes,4,opt,name=new_public_key,json=newPublicKey,proto3" json:"new_public_key,omitempty" yaml:"new_public_key"` - NewDiversifier string `protobuf:"bytes,5,opt,name=new_diversifier,json=newDiversifier,proto3" json:"new_diversifier,omitempty" yaml:"new_diversifier"` + Timestamp uint64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` + NewPublicKey *types.Any `protobuf:"bytes,3,opt,name=new_public_key,json=newPublicKey,proto3" json:"new_public_key,omitempty" yaml:"new_public_key"` + NewDiversifier string `protobuf:"bytes,4,opt,name=new_diversifier,json=newDiversifier,proto3" json:"new_diversifier,omitempty" yaml:"new_diversifier"` } func (m *Header) Reset() { *m = Header{} } @@ -383,52 +381,52 @@ func init() { } var fileDescriptor_264187157b9220a4 = []byte{ - // 711 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0xcd, 0x4e, 0xdb, 0x4a, - 0x14, 0xce, 0x04, 0x83, 0xc8, 0x24, 0x37, 0x70, 0xad, 0x80, 0x42, 0x74, 0x15, 0x47, 0x5e, 0xb1, - 0xc1, 0xbe, 0x80, 0xc4, 0x82, 0xbb, 0xb9, 0x04, 0x54, 0x55, 0x2d, 0x55, 0x2b, 0x43, 0x37, 0xdd, - 0x44, 0x63, 0x67, 0xe2, 0x8c, 0x6a, 0xcf, 0xa4, 0x99, 0x71, 0xa2, 0x54, 0x5d, 0x54, 0x5d, 0x75, - 0xd9, 0x45, 0xbb, 0xaf, 0x2a, 0xf5, 0x5d, 0xba, 0x64, 0xc9, 0x2a, 0xaa, 0xe0, 0x0d, 0xf2, 0x04, - 0x95, 0xc7, 0x4e, 0xfc, 0x03, 0x05, 0xa9, 0xed, 0x6e, 0xce, 0x99, 0xf3, 0xf3, 0x7d, 0xdf, 0x9c, - 0x63, 0xc3, 0x5d, 0x62, 0x3b, 0xa6, 0x47, 0xdc, 0xbe, 0x70, 0x3c, 0x82, 0xa9, 0xe0, 0x26, 0x67, - 0x1e, 0xf3, 0x91, 0xd3, 0x27, 0x14, 0x9b, 0xa3, 0xfd, 0xb4, 0x69, 0x0c, 0x86, 0x4c, 0x30, 0x55, - 0x23, 0xb6, 0x63, 0xa4, 0x53, 0x8c, 0x74, 0xcc, 0x68, 0xbf, 0x51, 0x73, 0x99, 0xcb, 0x64, 0xac, - 0x19, 0x9e, 0xa2, 0xb4, 0xc6, 0x96, 0xcb, 0x98, 0xeb, 0x61, 0x53, 0x5a, 0x76, 0xd0, 0x33, 0x11, - 0x9d, 0x44, 0x57, 0xfa, 0x25, 0x80, 0xe5, 0x63, 0x59, 0xeb, 0x4c, 0x20, 0x81, 0xd5, 0x06, 0x5c, - 0xe5, 0xf8, 0x55, 0x80, 0xa9, 0x83, 0xeb, 0xa0, 0x05, 0xb6, 0x15, 0x6b, 0x61, 0xab, 0xbb, 0xb0, - 0x44, 0x78, 0xa7, 0x37, 0x64, 0xaf, 0x31, 0xad, 0x17, 0x5b, 0x60, 0x7b, 0xb5, 0x5d, 0x9b, 0x4d, - 0xb5, 0xf5, 0x09, 0xf2, 0xbd, 0x43, 0x7d, 0x71, 0xa5, 0x5b, 0xab, 0x84, 0x3f, 0x90, 0x47, 0x55, - 0xc0, 0x35, 0x87, 0x51, 0x8e, 0x29, 0x0f, 0x78, 0x87, 0x87, 0x1d, 0xea, 0x4b, 0x2d, 0xb0, 0x5d, - 0xde, 0x33, 0x8d, 0x7b, 0xa8, 0x18, 0xc7, 0xf3, 0x3c, 0x09, 0xac, 0xdd, 0x98, 0x4d, 0xb5, 0xcd, - 0xa8, 0x53, 0xae, 0xa2, 0x6e, 0x55, 0x9d, 0x4c, 0xec, 0xa1, 0xf2, 0xfe, 0xb3, 0x56, 0xd0, 0xbf, - 0x00, 0x58, 0xcd, 0x16, 0x51, 0x1f, 0x41, 0x38, 0x08, 0x6c, 0x8f, 0x38, 0x9d, 0x97, 0x78, 0x22, - 0xf9, 0x95, 0xf7, 0x6a, 0x46, 0xa4, 0x8e, 0x31, 0x57, 0xc7, 0x38, 0xa2, 0x93, 0xf6, 0xc6, 0x6c, - 0xaa, 0xfd, 0x1d, 0xb5, 0x4b, 0x32, 0x74, 0xab, 0x14, 0x19, 0x8f, 0xf1, 0x44, 0x6d, 0xc1, 0x72, - 0x97, 0x8c, 0xf0, 0x90, 0x93, 0x1e, 0xc1, 0x43, 0xa9, 0x47, 0xc9, 0x4a, 0xbb, 0xd4, 0x7f, 0x60, - 0x49, 0x10, 0x1f, 0x73, 0x81, 0xfc, 0x81, 0xa4, 0xad, 0x58, 0x89, 0x23, 0x06, 0xf9, 0xae, 0x08, - 0x57, 0x1e, 0x62, 0xd4, 0xc5, 0xc3, 0x3b, 0xa5, 0xcf, 0x94, 0x2a, 0xe6, 0x4a, 0x85, 0xb7, 0x9c, - 0xb8, 0x14, 0x89, 0x60, 0x18, 0xe9, 0x5b, 0xb1, 0x12, 0x87, 0xfa, 0x1c, 0x56, 0x29, 0x1e, 0x77, - 0x52, 0xc4, 0x95, 0x3b, 0x88, 0x6f, 0xcd, 0xa6, 0xda, 0x46, 0x44, 0x3c, 0x9b, 0xa5, 0x5b, 0x15, - 0x8a, 0xc7, 0xcf, 0x16, 0xfc, 0x8f, 0xe1, 0x5a, 0x18, 0x90, 0xd6, 0x60, 0x39, 0xd4, 0x20, 0xfd, - 0x52, 0xb9, 0x00, 0xdd, 0x0a, 0x91, 0x9c, 0x24, 0x8e, 0x58, 0x84, 0x8f, 0x45, 0x58, 0x79, 0x42, - 0xb8, 0x8d, 0xfb, 0x68, 0x44, 0x58, 0x70, 0xb7, 0x14, 0x03, 0xf8, 0xd7, 0x82, 0x5b, 0x87, 0x51, - 0x2c, 0xe5, 0x28, 0xef, 0xed, 0xde, 0x3b, 0x50, 0x67, 0xf3, 0xac, 0x23, 0xda, 0x3d, 0x41, 0x02, - 0xb5, 0xeb, 0xb3, 0xa9, 0x56, 0x8b, 0x80, 0x66, 0x2a, 0xea, 0x56, 0x65, 0x61, 0x3f, 0xa5, 0xb9, - 0x8e, 0x62, 0xcc, 0xe2, 0x11, 0xfe, 0x53, 0x1d, 0xc5, 0x98, 0xa5, 0x3b, 0x9e, 0x8f, 0x59, 0x2c, - 0xcb, 0x1b, 0xb8, 0x9e, 0xaf, 0x90, 0x7d, 0x6a, 0x90, 0x7f, 0x6a, 0x15, 0x2a, 0x03, 0x24, 0xfa, - 0x52, 0x92, 0x8a, 0x25, 0xcf, 0xa1, 0xaf, 0x8b, 0x04, 0x8a, 0xe7, 0x42, 0x9e, 0xb3, 0xe3, 0xa4, - 0xdc, 0x3e, 0x99, 0x6f, 0x01, 0xac, 0x9f, 0xcf, 0x7d, 0xb8, 0xbb, 0x40, 0x22, 0x61, 0xfc, 0x0f, - 0xab, 0x09, 0x01, 0x59, 0x5e, 0x62, 0x49, 0x4f, 0x4f, 0xf6, 0x5e, 0xb7, 0x12, 0x0d, 0x4f, 0x6e, - 0x40, 0x28, 0xde, 0x0e, 0xe1, 0x13, 0x80, 0xa5, 0xb0, 0x6f, 0x7b, 0x22, 0x30, 0xff, 0x8d, 0xfd, - 0xc8, 0xad, 0xea, 0xd2, 0xcd, 0x55, 0x9d, 0x0b, 0xa7, 0xdc, 0x22, 0xdc, 0x72, 0x22, 0x5c, 0x8c, - 0xeb, 0x2b, 0x80, 0x30, 0x5a, 0x5a, 0x49, 0xe5, 0x14, 0x96, 0xe3, 0x55, 0xb9, 0xf7, 0xb3, 0xb2, - 0x39, 0x9b, 0x6a, 0x6a, 0x66, 0xbb, 0xe2, 0xef, 0x4a, 0xb4, 0x5a, 0x3f, 0xd9, 0xab, 0xe2, 0xaf, - 0xed, 0x55, 0xbb, 0xf7, 0xed, 0xaa, 0x09, 0x2e, 0xae, 0x9a, 0xe0, 0xfb, 0x55, 0x13, 0x7c, 0xb8, - 0x6e, 0x16, 0x2e, 0xae, 0x9b, 0x85, 0xcb, 0xeb, 0x66, 0xe1, 0xc5, 0xa9, 0x4b, 0x44, 0x3f, 0xb0, - 0x0d, 0x87, 0xf9, 0xa6, 0xc3, 0xb8, 0xcf, 0xb8, 0x49, 0x6c, 0x67, 0xc7, 0x65, 0xe6, 0xe8, 0xc0, - 0xf4, 0x59, 0x37, 0xf0, 0x30, 0x8f, 0xfe, 0x4d, 0x3b, 0xf3, 0x9f, 0xd3, 0xbf, 0x07, 0x3b, 0xa9, - 0xf1, 0xfe, 0x2f, 0x75, 0xb6, 0x57, 0x24, 0xc7, 0xfd, 0x1f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xdb, - 0x7e, 0xaf, 0x7a, 0xd2, 0x06, 0x00, 0x00, + // 708 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0xcd, 0x6e, 0xd3, 0x4a, + 0x14, 0xce, 0xa4, 0xbe, 0x55, 0x33, 0xc9, 0x4d, 0x7b, 0xad, 0xb4, 0x4a, 0xa3, 0xab, 0x38, 0xf2, + 0xaa, 0x9b, 0xda, 0xb7, 0xad, 0xd4, 0x45, 0xef, 0x86, 0xa6, 0x15, 0x42, 0x50, 0x04, 0x72, 0xcb, + 0x86, 0x4d, 0x34, 0x76, 0x26, 0xce, 0x08, 0x7b, 0x26, 0x64, 0xc6, 0x89, 0x82, 0x58, 0xb0, 0x64, + 0xc9, 0x02, 0xf6, 0x08, 0x89, 0x77, 0x61, 0xd9, 0x65, 0x57, 0x11, 0x6a, 0x25, 0x1e, 0x20, 0x4f, + 0x80, 0x3c, 0x76, 0xe2, 0x9f, 0x96, 0x54, 0x42, 0xec, 0xe6, 0x9c, 0x39, 0x3f, 0xdf, 0xf7, 0xcd, + 0x39, 0x36, 0xdc, 0x23, 0xb6, 0x63, 0x7a, 0xc4, 0xed, 0x0b, 0xc7, 0x23, 0x98, 0x0a, 0x6e, 0x72, + 0xe6, 0x31, 0x1f, 0x39, 0x7d, 0x42, 0xb1, 0x39, 0x3a, 0x48, 0x9b, 0xc6, 0x60, 0xc8, 0x04, 0x53, + 0x35, 0x62, 0x3b, 0x46, 0x3a, 0xc5, 0x48, 0xc7, 0x8c, 0x0e, 0x1a, 0x35, 0x97, 0xb9, 0x4c, 0xc6, + 0x9a, 0xe1, 0x29, 0x4a, 0x6b, 0x6c, 0xbb, 0x8c, 0xb9, 0x1e, 0x36, 0xa5, 0x65, 0x07, 0x3d, 0x13, + 0xd1, 0x49, 0x74, 0xa5, 0x5f, 0x01, 0x58, 0x3e, 0x91, 0xb5, 0xce, 0x05, 0x12, 0x58, 0x6d, 0xc0, + 0x35, 0x8e, 0x5f, 0x07, 0x98, 0x3a, 0xb8, 0x0e, 0x5a, 0x60, 0x47, 0xb1, 0x16, 0xb6, 0xba, 0x07, + 0x4b, 0x84, 0x77, 0x7a, 0x43, 0xf6, 0x06, 0xd3, 0x7a, 0xb1, 0x05, 0x76, 0xd6, 0xda, 0xb5, 0xd9, + 0x54, 0xdb, 0x98, 0x20, 0xdf, 0x3b, 0xd2, 0x17, 0x57, 0xba, 0xb5, 0x46, 0xf8, 0x43, 0x79, 0x54, + 0x05, 0x5c, 0x77, 0x18, 0xe5, 0x98, 0xf2, 0x80, 0x77, 0x78, 0xd8, 0xa1, 0xbe, 0xd2, 0x02, 0x3b, + 0xe5, 0x7d, 0xd3, 0xb8, 0x87, 0x8a, 0x71, 0x32, 0xcf, 0x93, 0xc0, 0xda, 0x8d, 0xd9, 0x54, 0xdb, + 0x8a, 0x3a, 0xe5, 0x2a, 0xea, 0x56, 0xd5, 0xc9, 0xc4, 0x1e, 0x29, 0xef, 0x3f, 0x6b, 0x05, 0xfd, + 0x0b, 0x80, 0xd5, 0x6c, 0x11, 0xf5, 0x31, 0x84, 0x83, 0xc0, 0xf6, 0x88, 0xd3, 0x79, 0x85, 0x27, + 0x92, 0x5f, 0x79, 0xbf, 0x66, 0x44, 0xea, 0x18, 0x73, 0x75, 0x8c, 0x63, 0x3a, 0x69, 0x6f, 0xce, + 0xa6, 0xda, 0x3f, 0x51, 0xbb, 0x24, 0x43, 0xb7, 0x4a, 0x91, 0xf1, 0x04, 0x4f, 0xd4, 0x16, 0x2c, + 0x77, 0xc9, 0x08, 0x0f, 0x39, 0xe9, 0x11, 0x3c, 0x94, 0x7a, 0x94, 0xac, 0xb4, 0x4b, 0xfd, 0x17, + 0x96, 0x04, 0xf1, 0x31, 0x17, 0xc8, 0x1f, 0x48, 0xda, 0x8a, 0x95, 0x38, 0x62, 0x90, 0x3f, 0x00, + 0x5c, 0x7d, 0x84, 0x51, 0x37, 0x1f, 0x0e, 0x72, 0xe1, 0xe1, 0x2d, 0x27, 0x2e, 0x45, 0x22, 0x18, + 0x62, 0xd9, 0xac, 0x62, 0x25, 0x0e, 0xf5, 0x05, 0xac, 0x52, 0x3c, 0xee, 0xa4, 0xc8, 0xad, 0x2c, + 0x21, 0xb7, 0x3d, 0x9b, 0x6a, 0x9b, 0x11, 0xb9, 0x6c, 0x96, 0x6e, 0x55, 0x28, 0x1e, 0x3f, 0x5f, + 0x70, 0x3c, 0x81, 0xeb, 0x61, 0x40, 0x9a, 0xa7, 0x12, 0xf2, 0x4c, 0xbf, 0x46, 0x2e, 0x40, 0xb7, + 0x42, 0x24, 0xa7, 0x89, 0x23, 0x26, 0xfa, 0xb1, 0x08, 0x2b, 0x4f, 0x09, 0xb7, 0x71, 0x1f, 0x8d, + 0x08, 0x0b, 0x86, 0x4b, 0x27, 0x6d, 0x00, 0xff, 0x5e, 0x70, 0xeb, 0x30, 0x1a, 0x11, 0x2e, 0xef, + 0xef, 0xdd, 0x3b, 0x34, 0xe7, 0xf3, 0xac, 0x63, 0xda, 0x3d, 0x45, 0x02, 0xb5, 0xeb, 0xb3, 0xa9, + 0x56, 0x8b, 0x80, 0x66, 0x2a, 0xea, 0x56, 0x65, 0x61, 0x3f, 0xa3, 0xb9, 0x8e, 0x62, 0xcc, 0x62, + 0xfd, 0xfe, 0x54, 0x47, 0x31, 0x66, 0xe9, 0x8e, 0x17, 0x63, 0x16, 0xcb, 0xf2, 0x16, 0x6e, 0xe4, + 0x2b, 0x64, 0x9f, 0x1a, 0xe4, 0x9f, 0x5a, 0x85, 0xca, 0x00, 0x89, 0x7e, 0x3c, 0x03, 0xf2, 0x1c, + 0xfa, 0xba, 0x48, 0x20, 0x09, 0xba, 0x62, 0xc9, 0x73, 0x76, 0x9c, 0x94, 0xbb, 0xa7, 0xef, 0x1d, + 0x80, 0xf5, 0x8b, 0xb9, 0x0f, 0x77, 0x17, 0x48, 0x24, 0x8c, 0x07, 0xb0, 0x9a, 0x10, 0x90, 0xe5, + 0x25, 0x96, 0xf4, 0xf4, 0x64, 0xef, 0x75, 0x2b, 0xd1, 0xf0, 0xf4, 0x16, 0x84, 0xe2, 0xdd, 0x10, + 0x3e, 0x01, 0x58, 0x0a, 0xfb, 0xb6, 0x27, 0x02, 0xf3, 0xa5, 0x43, 0xb1, 0xb4, 0x5a, 0x7e, 0x1d, + 0x57, 0x6e, 0xaf, 0xe3, 0x5c, 0x38, 0xe5, 0x0e, 0xe1, 0xfe, 0x4a, 0x84, 0x8b, 0x71, 0x7d, 0x05, + 0x10, 0x46, 0x8b, 0x29, 0xa9, 0x9c, 0xc1, 0x72, 0xbc, 0x2a, 0xf7, 0x7e, 0x3a, 0xb6, 0x66, 0x53, + 0x4d, 0xcd, 0x6c, 0x57, 0xfc, 0xed, 0x88, 0x56, 0xeb, 0x17, 0x7b, 0x55, 0xfc, 0xbd, 0xbd, 0x6a, + 0xf7, 0xbe, 0x5d, 0x37, 0xc1, 0xe5, 0x75, 0x13, 0x7c, 0xbf, 0x6e, 0x82, 0x0f, 0x37, 0xcd, 0xc2, + 0xe5, 0x4d, 0xb3, 0x70, 0x75, 0xd3, 0x2c, 0xbc, 0x3c, 0x73, 0x89, 0xe8, 0x07, 0xb6, 0xe1, 0x30, + 0xdf, 0x74, 0x18, 0xf7, 0x19, 0x37, 0x89, 0xed, 0xec, 0xba, 0xcc, 0x1c, 0x1d, 0x9a, 0x3e, 0xeb, + 0x06, 0x1e, 0xe6, 0xd1, 0xff, 0x67, 0x77, 0xfe, 0x03, 0xfa, 0xef, 0x70, 0x37, 0x35, 0xde, 0xff, + 0xa7, 0xce, 0xf6, 0xaa, 0xe4, 0x78, 0xf0, 0x33, 0x00, 0x00, 0xff, 0xff, 0x01, 0xee, 0x32, 0x83, + 0xb6, 0x06, 0x00, 0x00, } func (m *ClientState) Marshal() (dAtA []byte, err error) { @@ -553,7 +551,7 @@ func (m *Header) MarshalToSizedBuffer(dAtA []byte) (int, error) { copy(dAtA[i:], m.NewDiversifier) i = encodeVarintSolomachine(dAtA, i, uint64(len(m.NewDiversifier))) i-- - dAtA[i] = 0x2a + dAtA[i] = 0x22 } if m.NewPublicKey != nil { { @@ -565,23 +563,18 @@ func (m *Header) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintSolomachine(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x22 + dAtA[i] = 0x1a } if len(m.Signature) > 0 { i -= len(m.Signature) copy(dAtA[i:], m.Signature) i = encodeVarintSolomachine(dAtA, i, uint64(len(m.Signature))) i-- - dAtA[i] = 0x1a + dAtA[i] = 0x12 } if m.Timestamp != 0 { i = encodeVarintSolomachine(dAtA, i, uint64(m.Timestamp)) i-- - dAtA[i] = 0x10 - } - if m.Sequence != 0 { - i = encodeVarintSolomachine(dAtA, i, uint64(m.Sequence)) - i-- dAtA[i] = 0x8 } return len(dAtA) - i, nil @@ -875,9 +868,6 @@ func (m *Header) Size() (n int) { } var l int _ = l - if m.Sequence != 0 { - n += 1 + sovSolomachine(uint64(m.Sequence)) - } if m.Timestamp != 0 { n += 1 + sovSolomachine(uint64(m.Timestamp)) } @@ -1298,25 +1288,6 @@ func (m *Header) Unmarshal(dAtA []byte) error { } switch fieldNum { case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Sequence", wireType) - } - m.Sequence = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Sequence |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 2: if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) } @@ -1335,7 +1306,7 @@ func (m *Header) Unmarshal(dAtA []byte) error { break } } - case 3: + case 2: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Signature", wireType) } @@ -1369,7 +1340,7 @@ func (m *Header) Unmarshal(dAtA []byte) error { m.Signature = []byte{} } iNdEx = postIndex - case 4: + case 3: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field NewPublicKey", wireType) } @@ -1405,7 +1376,7 @@ func (m *Header) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 5: + case 4: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field NewDiversifier", wireType) } diff --git a/modules/light-clients/06-solomachine/update.go b/modules/light-clients/06-solomachine/update.go index 2ccd4d74add..fc1bab93601 100644 --- a/modules/light-clients/06-solomachine/update.go +++ b/modules/light-clients/06-solomachine/update.go @@ -26,14 +26,6 @@ func (cs ClientState) VerifyClientMessage(ctx sdk.Context, cdc codec.BinaryCodec } func (cs ClientState) verifyHeader(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, header *Header) error { - // assert update sequence is current sequence - if header.Sequence != cs.Sequence { - return sdkerrors.Wrapf( - clienttypes.ErrInvalidHeader, - "header sequence does not match the client state sequence (%d != %d)", header.Sequence, cs.Sequence, - ) - } - // assert update timestamp is not less than current consensus state timestamp if header.Timestamp < cs.ConsensusState.Timestamp { return sdkerrors.Wrapf( @@ -54,7 +46,7 @@ func (cs ClientState) verifyHeader(ctx sdk.Context, cdc codec.BinaryCodec, clien } signBytes := &SignBytes{ - Sequence: header.Sequence, + Sequence: cs.Sequence, Timestamp: header.Timestamp, Diversifier: cs.ConsensusState.Diversifier, Path: []byte(SentinelHeaderPath), diff --git a/modules/light-clients/06-solomachine/update_test.go b/modules/light-clients/06-solomachine/update_test.go index a8311fbcfbf..8a251dc22cf 100644 --- a/modules/light-clients/06-solomachine/update_test.go +++ b/modules/light-clients/06-solomachine/update_test.go @@ -54,16 +54,6 @@ func (suite *SoloMachineTestSuite) TestVerifyClientMessageHeader() { }, false, }, - { - "wrong sequence in header", - func() { - // store in temp before assigning to interface type - h := sm.CreateHeader(sm.Diversifier) - h.Sequence++ - clientMsg = h - }, - false, - }, { "invalid header Signature", func() { @@ -458,7 +448,6 @@ func (suite *SoloMachineTestSuite) TestUpdateState() { suite.Require().Equal(newClientState.(*solomachine.ClientState).Sequence, consensusHeights[0].GetRevisionHeight()) suite.Require().False(newClientState.(*solomachine.ClientState).IsFrozen) - suite.Require().Equal(clientMsg.(*solomachine.Header).Sequence+1, newClientState.(*solomachine.ClientState).Sequence) suite.Require().Equal(clientMsg.(*solomachine.Header).NewPublicKey, newClientState.(*solomachine.ClientState).ConsensusState.PublicKey) suite.Require().Equal(clientMsg.(*solomachine.Header).NewDiversifier, newClientState.(*solomachine.ClientState).ConsensusState.Diversifier) suite.Require().Equal(clientMsg.(*solomachine.Header).Timestamp, newClientState.(*solomachine.ClientState).ConsensusState.Timestamp) diff --git a/proto/ibc/applications/transfer/v2/authz.proto b/proto/ibc/applications/transfer/v2/authz.proto new file mode 100644 index 00000000000..53ee25fc1cb --- /dev/null +++ b/proto/ibc/applications/transfer/v2/authz.proto @@ -0,0 +1,30 @@ +syntax = "proto3"; + +package ibc.applications.transfer.v2; + +option go_package = "github.com/cosmos/ibc-go/v6/modules/apps/transfer/types"; + +import "cosmos_proto/cosmos.proto"; +import "gogoproto/gogo.proto"; +import "cosmos/base/v1beta1/coin.proto"; + +message PortChannelAmount { + // the port on which the packet will be sent + string source_port = 1 [(gogoproto.moretags) = "yaml:\"source_port\""]; + // the channel by which the packet will be sent + string source_channel = 2 [(gogoproto.moretags) = "yaml:\"source_channel\""]; + // spend limitation on the channel + 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; +} + +// TransferAuthorization allows the grantee to spend up to spend_limit coins from +// the granter's account for ibc transfer on a specific channel +message TransferAuthorization { + option (cosmos_proto.implements_interface) = "Authorization"; + + // port and channel amounts + repeated PortChannelAmount allocations = 1 [(gogoproto.nullable) = false]; +} diff --git a/proto/ibc/lightclients/solomachine/v3/solomachine.proto b/proto/ibc/lightclients/solomachine/v3/solomachine.proto index 8203c17796b..09bc97a9aa7 100644 --- a/proto/ibc/lightclients/solomachine/v3/solomachine.proto +++ b/proto/ibc/lightclients/solomachine/v3/solomachine.proto @@ -35,12 +35,11 @@ message ConsensusState { // Header defines a solo machine consensus header message Header { option (gogoproto.goproto_getters) = false; - // sequence to update solo machine public key at - uint64 sequence = 1; - uint64 timestamp = 2; - bytes signature = 3; - google.protobuf.Any new_public_key = 4 [(gogoproto.moretags) = "yaml:\"new_public_key\""]; - string new_diversifier = 5 [(gogoproto.moretags) = "yaml:\"new_diversifier\""]; + + uint64 timestamp = 1; + bytes signature = 2; + google.protobuf.Any new_public_key = 3 [(gogoproto.moretags) = "yaml:\"new_public_key\""]; + string new_diversifier = 4 [(gogoproto.moretags) = "yaml:\"new_diversifier\""]; } // Misbehaviour defines misbehaviour for a solo machine which consists @@ -57,18 +56,20 @@ message Misbehaviour { // signature. message SignatureAndData { option (gogoproto.goproto_getters) = false; - bytes signature = 1; - bytes path = 2; - bytes data = 3; - uint64 timestamp = 4; + + bytes signature = 1; + bytes path = 2; + bytes data = 3; + uint64 timestamp = 4; } // TimestampedSignatureData contains the signature data and the timestamp of the // signature. message TimestampedSignatureData { option (gogoproto.goproto_getters) = false; - bytes signature_data = 1 [(gogoproto.moretags) = "yaml:\"signature_data\""]; - uint64 timestamp = 2; + + bytes signature_data = 1 [(gogoproto.moretags) = "yaml:\"signature_data\""]; + uint64 timestamp = 2; } // SignBytes defines the signed bytes used for signature verification. diff --git a/testing/solomachine.go b/testing/solomachine.go index 0b996781f0a..21dcd67ebcd 100644 --- a/testing/solomachine.go +++ b/testing/solomachine.go @@ -174,7 +174,6 @@ func (solo *Solomachine) CreateHeader(newDiversifier string) *solomachine.Header sig := solo.GenerateSignature(bz) header := &solomachine.Header{ - Sequence: solo.Sequence, Timestamp: solo.Time, Signature: sig, NewPublicKey: publicKey, From 015bce10cc6f5270bb99b584c0ae5eb50395dab4 Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Mon, 9 Jan 2023 17:20:47 +0100 Subject: [PATCH 02/18] chore: moving authz protos to transfer.v1 (#2984) * moving authz protos to transfer.v1 * running make format --- go.mod | 2 +- .../apps/transfer/keeper/msg_server_test.go | 4 +- modules/apps/transfer/types/authz.pb.go | 72 +++++++++---------- modules/apps/transfer/types/transfer_authz.go | 4 +- .../transfer/types/transfer_authz_test.go | 10 +-- .../transfer/{v2 => v1}/authz.proto | 2 +- 6 files changed, 45 insertions(+), 49 deletions(-) rename proto/ibc/applications/transfer/{v2 => v1}/authz.proto (96%) diff --git a/go.mod b/go.mod index caf7821c07e..94a97dc4cba 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( github.com/stretchr/testify v1.8.1 github.com/tendermint/tendermint v0.34.23 github.com/tendermint/tm-db v0.6.7 + golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e google.golang.org/grpc v1.51.0 google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8 @@ -140,7 +141,6 @@ require ( go.etcd.io/bbolt v1.3.6 // indirect go.opencensus.io v0.23.0 // indirect golang.org/x/crypto v0.2.0 // indirect - golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect golang.org/x/net v0.2.0 // indirect golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect golang.org/x/sys v0.2.0 // indirect diff --git a/modules/apps/transfer/keeper/msg_server_test.go b/modules/apps/transfer/keeper/msg_server_test.go index e457d3894cb..e11b2b1dfce 100644 --- a/modules/apps/transfer/keeper/msg_server_test.go +++ b/modules/apps/transfer/keeper/msg_server_test.go @@ -9,9 +9,7 @@ import ( ) func (suite *KeeperTestSuite) TestMsgTransfer() { - var ( - msg *types.MsgTransfer - ) + var msg *types.MsgTransfer testCases := []struct { name string diff --git a/modules/apps/transfer/types/authz.pb.go b/modules/apps/transfer/types/authz.pb.go index db9a9e3dbc3..403bd32352d 100644 --- a/modules/apps/transfer/types/authz.pb.go +++ b/modules/apps/transfer/types/authz.pb.go @@ -1,15 +1,15 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: ibc/applications/transfer/v2/authz.proto +// source: ibc/applications/transfer/v1/authz.proto package types import ( fmt "fmt" + _ "github.com/cosmos/cosmos-proto" github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" types "github.com/cosmos/cosmos-sdk/types" _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" - _ "github.com/regen-network/cosmos-proto" io "io" math "math" math_bits "math/bits" @@ -41,7 +41,7 @@ func (m *PortChannelAmount) Reset() { *m = PortChannelAmount{} } func (m *PortChannelAmount) String() string { return proto.CompactTextString(m) } func (*PortChannelAmount) ProtoMessage() {} func (*PortChannelAmount) Descriptor() ([]byte, []int) { - return fileDescriptor_c4c17169771443ae, []int{0} + return fileDescriptor_b1a28b55d17325aa, []int{0} } func (m *PortChannelAmount) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -109,7 +109,7 @@ func (m *TransferAuthorization) Reset() { *m = TransferAuthorization{} } func (m *TransferAuthorization) String() string { return proto.CompactTextString(m) } func (*TransferAuthorization) ProtoMessage() {} func (*TransferAuthorization) Descriptor() ([]byte, []int) { - return fileDescriptor_c4c17169771443ae, []int{1} + return fileDescriptor_b1a28b55d17325aa, []int{1} } func (m *TransferAuthorization) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -146,44 +146,44 @@ func (m *TransferAuthorization) GetAllocations() []PortChannelAmount { } func init() { - proto.RegisterType((*PortChannelAmount)(nil), "ibc.applications.transfer.v2.PortChannelAmount") - proto.RegisterType((*TransferAuthorization)(nil), "ibc.applications.transfer.v2.TransferAuthorization") + proto.RegisterType((*PortChannelAmount)(nil), "ibc.applications.transfer.v1.PortChannelAmount") + proto.RegisterType((*TransferAuthorization)(nil), "ibc.applications.transfer.v1.TransferAuthorization") } func init() { - proto.RegisterFile("ibc/applications/transfer/v2/authz.proto", fileDescriptor_c4c17169771443ae) + proto.RegisterFile("ibc/applications/transfer/v1/authz.proto", fileDescriptor_b1a28b55d17325aa) } -var fileDescriptor_c4c17169771443ae = []byte{ +var fileDescriptor_b1a28b55d17325aa = []byte{ // 442 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x52, 0xc1, 0x6a, 0xdb, 0x30, - 0x18, 0x8e, 0x9b, 0x32, 0xa8, 0x42, 0xc7, 0x62, 0xd6, 0xe1, 0x94, 0xe1, 0x04, 0x9f, 0x0c, 0x23, - 0xd2, 0x9a, 0xc1, 0x0a, 0x3d, 0x2d, 0xe9, 0x75, 0x87, 0xcd, 0x0c, 0x06, 0xbb, 0x04, 0x59, 0xd6, - 0x12, 0x31, 0x5b, 0xbf, 0x91, 0xe4, 0x8c, 0xf6, 0xba, 0x17, 0xd8, 0x6b, 0x6c, 0xe7, 0x3d, 0x44, - 0x8f, 0x65, 0xa7, 0x9d, 0xb2, 0x91, 0xbc, 0x41, 0x9f, 0x60, 0x58, 0x52, 0x21, 0xa5, 0xd0, 0x93, - 0xad, 0xff, 0xfb, 0xfe, 0x4f, 0xfa, 0xbf, 0xef, 0x47, 0xa9, 0xc8, 0x19, 0xa1, 0x75, 0x5d, 0x0a, - 0x46, 0x8d, 0x00, 0xa9, 0x89, 0x51, 0x54, 0xea, 0xcf, 0x5c, 0x91, 0xd5, 0x84, 0xd0, 0xc6, 0x2c, - 0x2f, 0x71, 0xad, 0xc0, 0x40, 0xf8, 0x5c, 0xe4, 0x0c, 0xef, 0x32, 0xf1, 0x2d, 0x13, 0xaf, 0x26, - 0xc7, 0x03, 0x06, 0xba, 0x02, 0x3d, 0xb7, 0x5c, 0xe2, 0x0e, 0xae, 0xf1, 0xf8, 0xe9, 0x02, 0x16, - 0xe0, 0xea, 0xed, 0x9f, 0xaf, 0xc6, 0x8e, 0x43, 0x72, 0xaa, 0x39, 0x59, 0x9d, 0xe4, 0xdc, 0xd0, - 0x13, 0xc2, 0x40, 0x48, 0x87, 0x27, 0x3f, 0xf6, 0x50, 0xff, 0x1d, 0x28, 0x73, 0xbe, 0xa4, 0x52, - 0xf2, 0x72, 0x5a, 0x41, 0x23, 0x4d, 0x78, 0x8a, 0x7a, 0x1a, 0x1a, 0xc5, 0xf8, 0xbc, 0x06, 0x65, - 0xa2, 0x60, 0x14, 0xa4, 0x07, 0xb3, 0x67, 0x37, 0xeb, 0x61, 0x78, 0x41, 0xab, 0xf2, 0x2c, 0xd9, - 0x01, 0x93, 0x0c, 0xb9, 0x53, 0xab, 0x12, 0xbe, 0x41, 0x8f, 0x3d, 0xc6, 0x9c, 0x60, 0xb4, 0x67, - 0x7b, 0x07, 0x37, 0xeb, 0xe1, 0xd1, 0x9d, 0x5e, 0x8f, 0x27, 0xd9, 0xa1, 0x2b, 0xf8, 0x07, 0x84, - 0x25, 0xea, 0xe9, 0x9a, 0xcb, 0x62, 0x5e, 0x8a, 0x4a, 0x98, 0xa8, 0x3b, 0xea, 0xa6, 0xbd, 0xc9, - 0x00, 0xfb, 0x51, 0xdb, 0x31, 0xb0, 0x1f, 0x03, 0x9f, 0x83, 0x90, 0xb3, 0x97, 0x57, 0xeb, 0x61, - 0xe7, 0xe7, 0xdf, 0x61, 0xba, 0x10, 0x66, 0xd9, 0xe4, 0x98, 0x41, 0xe5, 0x7d, 0xf1, 0x9f, 0xb1, - 0x2e, 0xbe, 0x10, 0x73, 0x51, 0x73, 0x6d, 0x1b, 0x74, 0x86, 0xac, 0xfe, 0xdb, 0x56, 0x3e, 0x7c, - 0x81, 0xfa, 0xb4, 0x2c, 0xe1, 0x2b, 0x2f, 0xe6, 0xb4, 0x28, 0x14, 0xd7, 0x9a, 0xeb, 0x68, 0x7f, - 0xd4, 0x4d, 0x0f, 0xb2, 0x27, 0x1e, 0x98, 0xde, 0xd6, 0x93, 0x6f, 0x01, 0x3a, 0xfa, 0xe0, 0xc3, - 0x98, 0x36, 0x66, 0x09, 0x4a, 0x5c, 0xda, 0x8c, 0xc2, 0x8f, 0xa8, 0xd7, 0xb2, 0x7d, 0x62, 0x51, - 0x60, 0x1f, 0x4d, 0xf0, 0x43, 0x51, 0xe2, 0x7b, 0xae, 0xcf, 0xf6, 0xdb, 0x51, 0xb2, 0x5d, 0xa5, - 0xb3, 0xfe, 0xef, 0x5f, 0xe3, 0xc3, 0x3b, 0x77, 0xcd, 0xde, 0x5f, 0x6d, 0xe2, 0xe0, 0x7a, 0x13, - 0x07, 0xff, 0x36, 0x71, 0xf0, 0x7d, 0x1b, 0x77, 0xae, 0xb7, 0x71, 0xe7, 0xcf, 0x36, 0xee, 0x7c, - 0x3a, 0xbd, 0x6f, 0x81, 0xc8, 0xd9, 0x78, 0x01, 0x64, 0xf5, 0x9a, 0x54, 0x50, 0x34, 0x25, 0xd7, - 0xed, 0x12, 0xee, 0x2c, 0x9f, 0xf5, 0x25, 0x7f, 0x64, 0x77, 0xe1, 0xd5, 0xff, 0x00, 0x00, 0x00, - 0xff, 0xff, 0x1b, 0x30, 0xdf, 0x96, 0xa6, 0x02, 0x00, 0x00, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x52, 0xc1, 0x8a, 0x13, 0x31, + 0x18, 0xee, 0x6c, 0x17, 0x61, 0x53, 0x56, 0xec, 0xe0, 0xca, 0x74, 0x91, 0x69, 0x99, 0xd3, 0x80, + 0x34, 0xb1, 0x0a, 0x2e, 0xec, 0xc9, 0x76, 0xaf, 0x1e, 0x74, 0x10, 0x04, 0x2f, 0x25, 0x93, 0x89, + 0x6d, 0x70, 0x26, 0xff, 0x90, 0x64, 0x2a, 0xbb, 0x57, 0x5f, 0xc0, 0xd7, 0xd0, 0xb3, 0x0f, 0xb1, + 0x78, 0xda, 0xa3, 0xa7, 0x2a, 0xed, 0x1b, 0xec, 0x13, 0xc8, 0x24, 0x59, 0xe8, 0x52, 0xf0, 0x34, + 0x93, 0xff, 0xfb, 0xfe, 0x2f, 0xf9, 0xbf, 0xef, 0x47, 0xa9, 0xc8, 0x19, 0xa1, 0x75, 0x5d, 0x0a, + 0x46, 0x8d, 0x00, 0xa9, 0x89, 0x51, 0x54, 0xea, 0x4f, 0x5c, 0x91, 0xd5, 0x84, 0xd0, 0xc6, 0x2c, + 0xaf, 0x70, 0xad, 0xc0, 0x40, 0xf8, 0x54, 0xe4, 0x0c, 0xef, 0x32, 0xf1, 0x1d, 0x13, 0xaf, 0x26, + 0xa7, 0x03, 0x06, 0xba, 0x02, 0x3d, 0xb7, 0x5c, 0xe2, 0x0e, 0xae, 0xf1, 0xf4, 0xf1, 0x02, 0x16, + 0xe0, 0xea, 0xed, 0x9f, 0xaf, 0xc6, 0x8e, 0x43, 0x72, 0xaa, 0x39, 0x59, 0x4d, 0x72, 0x6e, 0xe8, + 0x84, 0x30, 0x10, 0xd2, 0xe1, 0xc9, 0xf7, 0x03, 0xd4, 0x7f, 0x0b, 0xca, 0x5c, 0x2c, 0xa9, 0x94, + 0xbc, 0x9c, 0x56, 0xd0, 0x48, 0x13, 0x9e, 0xa1, 0x9e, 0x86, 0x46, 0x31, 0x3e, 0xaf, 0x41, 0x99, + 0x28, 0x18, 0x05, 0xe9, 0xd1, 0xec, 0xc9, 0xed, 0x7a, 0x18, 0x5e, 0xd2, 0xaa, 0x3c, 0x4f, 0x76, + 0xc0, 0x24, 0x43, 0xee, 0xd4, 0xaa, 0x84, 0xaf, 0xd1, 0x43, 0x8f, 0x31, 0x27, 0x18, 0x1d, 0xd8, + 0xde, 0xc1, 0xed, 0x7a, 0x78, 0x72, 0xaf, 0xd7, 0xe3, 0x49, 0x76, 0xec, 0x0a, 0xfe, 0x01, 0x61, + 0x89, 0x7a, 0xba, 0xe6, 0xb2, 0x98, 0x97, 0xa2, 0x12, 0x26, 0xea, 0x8e, 0xba, 0x69, 0xef, 0xc5, + 0x00, 0xfb, 0x51, 0xdb, 0x31, 0xb0, 0x1f, 0x03, 0x5f, 0x80, 0x90, 0xb3, 0xe7, 0xd7, 0xeb, 0x61, + 0xe7, 0xc7, 0x9f, 0x61, 0xba, 0x10, 0x66, 0xd9, 0xe4, 0x98, 0x41, 0xe5, 0x7d, 0xf1, 0x9f, 0xb1, + 0x2e, 0x3e, 0x13, 0x73, 0x59, 0x73, 0x6d, 0x1b, 0x74, 0x86, 0xac, 0xfe, 0x9b, 0x56, 0x3e, 0x7c, + 0x86, 0xfa, 0xb4, 0x2c, 0xe1, 0x0b, 0x2f, 0xe6, 0xb4, 0x28, 0x14, 0xd7, 0x9a, 0xeb, 0xe8, 0x70, + 0xd4, 0x4d, 0x8f, 0xb2, 0x47, 0x1e, 0x98, 0xde, 0xd5, 0x93, 0xaf, 0x01, 0x3a, 0x79, 0xef, 0xc3, + 0x98, 0x36, 0x66, 0x09, 0x4a, 0x5c, 0xd9, 0x8c, 0xc2, 0x0f, 0xa8, 0xd7, 0xb2, 0x7d, 0x62, 0x51, + 0x60, 0x1f, 0x4d, 0xf0, 0xff, 0xa2, 0xc4, 0x7b, 0xae, 0xcf, 0x0e, 0xdb, 0x51, 0xb2, 0x5d, 0xa5, + 0xf3, 0xfe, 0xaf, 0x9f, 0xe3, 0xe3, 0x7b, 0x77, 0xcd, 0xde, 0x5d, 0x6f, 0xe2, 0xe0, 0x66, 0x13, + 0x07, 0x7f, 0x37, 0x71, 0xf0, 0x6d, 0x1b, 0x77, 0x6e, 0xb6, 0x71, 0xe7, 0xf7, 0x36, 0xee, 0x7c, + 0x3c, 0xdb, 0xb7, 0x40, 0xe4, 0x6c, 0xbc, 0x00, 0xb2, 0x7a, 0x45, 0x2a, 0x28, 0x9a, 0x92, 0xeb, + 0x76, 0x09, 0x77, 0x96, 0xcf, 0xfa, 0x92, 0x3f, 0xb0, 0xbb, 0xf0, 0xf2, 0x5f, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x50, 0xcc, 0x73, 0x94, 0xa6, 0x02, 0x00, 0x00, } func (m *PortChannelAmount) Marshal() (dAtA []byte, err error) { diff --git a/modules/apps/transfer/types/transfer_authz.go b/modules/apps/transfer/types/transfer_authz.go index bcf6e3ebb27..585106e2e9c 100644 --- a/modules/apps/transfer/types/transfer_authz.go +++ b/modules/apps/transfer/types/transfer_authz.go @@ -11,9 +11,7 @@ import ( const gasCostPerIteration = uint64(10) -var ( - _ authz.Authorization = &TransferAuthorization{} -) +var _ authz.Authorization = &TransferAuthorization{} // NewTransferAuthorization creates a new TransferAuthorization object. func NewTransferAuthorization(sourcePorts, sourceChannels []string, spendLimits []sdk.Coins, allowedAddrs [][]string) *TransferAuthorization { diff --git a/modules/apps/transfer/types/transfer_authz_test.go b/modules/apps/transfer/types/transfer_authz_test.go index 022188e747c..873303d7e7a 100644 --- a/modules/apps/transfer/types/transfer_authz_test.go +++ b/modules/apps/transfer/types/transfer_authz_test.go @@ -31,7 +31,7 @@ func TestTransferAuthorization(t *testing.T) { t.Log("verify authorization returns valid method name") require.Equal(t, authorization.MsgTypeURL(), "/ibc.applications.transfer.v1.MsgTransfer") require.NoError(t, authorization.ValidateBasic()) - transfer := NewMsgTransfer(sourcePort, sourceChannel, coin1000, fromAddr.String(), toAddr.String(), timeoutHeight, 0) + transfer := NewMsgTransfer(sourcePort, sourceChannel, coin1000, fromAddr.String(), toAddr.String(), timeoutHeight, 0, "") require.NoError(t, authorization.ValidateBasic()) t.Log("verify updated authorization returns nil") @@ -44,7 +44,7 @@ func TestTransferAuthorization(t *testing.T) { authorization = NewTransferAuthorization([]string{sourcePort}, []string{sourceChannel}, []sdk.Coins{coins1000}, [][]string{{toAddr.String()}}) require.Equal(t, authorization.MsgTypeURL(), "/ibc.applications.transfer.v1.MsgTransfer") require.NoError(t, authorization.ValidateBasic()) - transfer = NewMsgTransfer(sourcePort, sourceChannel, coin500, fromAddr.String(), toAddr.String(), timeoutHeight, 0) + transfer = NewMsgTransfer(sourcePort, sourceChannel, coin500, fromAddr.String(), toAddr.String(), timeoutHeight, 0, "") require.NoError(t, authorization.ValidateBasic()) resp, err = authorization.Accept(ctx, transfer) require.NoError(t, err) @@ -61,7 +61,7 @@ func TestTransferAuthorization(t *testing.T) { t.Log("expect error when spend limit for specific port and channel is not set") authorization = NewTransferAuthorization([]string{sourcePort}, []string{sourceChannel}, []sdk.Coins{coins1000}, [][]string{{toAddr.String()}}) - transfer = NewMsgTransfer(sourcePort2, sourceChannel2, coin500, fromAddr.String(), toAddr.String(), timeoutHeight, 0) + transfer = NewMsgTransfer(sourcePort2, sourceChannel2, coin500, fromAddr.String(), toAddr.String(), timeoutHeight, 0, "") _, err = authorization.Accept(ctx, transfer) require.Error(t, err) @@ -71,7 +71,7 @@ func TestTransferAuthorization(t *testing.T) { []string{sourceChannel, sourceChannel2}, []sdk.Coins{coins1000, coins1000}, [][]string{{toAddr.String()}, {toAddr.String()}}) - transfer = NewMsgTransfer(sourcePort, sourceChannel, coin1000, fromAddr.String(), toAddr.String(), timeoutHeight, 0) + transfer = NewMsgTransfer(sourcePort, sourceChannel, coin1000, fromAddr.String(), toAddr.String(), timeoutHeight, 0, "") resp, err = authorization.Accept(ctx, transfer) require.NoError(t, err) require.NotNil(t, resp.Updated) @@ -80,7 +80,7 @@ func TestTransferAuthorization(t *testing.T) { t.Log("expect error when transferring to not allowed address") authorization = NewTransferAuthorization([]string{sourcePort}, []string{sourceChannel}, []sdk.Coins{coins1000}, [][]string{{fromAddr.String()}}) - transfer = NewMsgTransfer(sourcePort, sourceChannel, coin500, fromAddr.String(), toAddr.String(), timeoutHeight, 0) + transfer = NewMsgTransfer(sourcePort, sourceChannel, coin500, fromAddr.String(), toAddr.String(), timeoutHeight, 0, "") _, err = authorization.Accept(ctx, transfer) require.Error(t, err) } diff --git a/proto/ibc/applications/transfer/v2/authz.proto b/proto/ibc/applications/transfer/v1/authz.proto similarity index 96% rename from proto/ibc/applications/transfer/v2/authz.proto rename to proto/ibc/applications/transfer/v1/authz.proto index 53ee25fc1cb..b1aa9b2adb1 100644 --- a/proto/ibc/applications/transfer/v2/authz.proto +++ b/proto/ibc/applications/transfer/v1/authz.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -package ibc.applications.transfer.v2; +package ibc.applications.transfer.v1; option go_package = "github.com/cosmos/ibc-go/v6/modules/apps/transfer/types"; From 49f8112511653e53566e364a280aed022a9df49f Mon Sep 17 00:00:00 2001 From: Cian Hatton Date: Mon, 9 Jan 2023 16:34:51 +0000 Subject: [PATCH 03/18] Make isAllowedAddress private (#2985) --- modules/apps/transfer/types/transfer_authz.go | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/modules/apps/transfer/types/transfer_authz.go b/modules/apps/transfer/types/transfer_authz.go index 585106e2e9c..1baee282b3f 100644 --- a/modules/apps/transfer/types/transfer_authz.go +++ b/modules/apps/transfer/types/transfer_authz.go @@ -4,6 +4,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/authz" + host "github.com/cosmos/ibc-go/v6/modules/core/24-host" "golang.org/x/exp/slices" @@ -34,16 +35,6 @@ func (a TransferAuthorization) MsgTypeURL() string { return sdk.MsgTypeURL(&MsgTransfer{}) } -func IsAllowedAddress(ctx sdk.Context, receiver string, allowedAddrs []string) bool { - for _, addr := range allowedAddrs { - ctx.GasMeter().ConsumeGas(gasCostPerIteration, "transfer authorization") - if addr == receiver { - return true - } - } - return false -} - // Accept implements Authorization.Accept. func (a TransferAuthorization) Accept(ctx sdk.Context, msg sdk.Msg) (authz.AcceptResponse, error) { msgTransfer, ok := msg.(*MsgTransfer) @@ -58,7 +49,7 @@ func (a TransferAuthorization) Accept(ctx sdk.Context, msg sdk.Msg) (authz.Accep return authz.AcceptResponse{}, sdkerrors.ErrInsufficientFunds.Wrapf("requested amount is more than spend limit") } - if !IsAllowedAddress(ctx, msgTransfer.Receiver, allocation.AllowedAddresses) { + if !isAllowedAddress(ctx, msgTransfer.Receiver, allocation.AllowedAddresses) { return authz.AcceptResponse{}, sdkerrors.ErrInvalidAddress.Wrapf("not allowed address for transfer") } @@ -112,3 +103,15 @@ func (a TransferAuthorization) ValidateBasic() error { } return nil } + +// isAllowedAddress returns a boolean indicating if the receiver address is valid for transfer. +// gasCostPerIteration gas is consumed for each iteration. +func isAllowedAddress(ctx sdk.Context, receiver string, allowedAddrs []string) bool { + for _, addr := range allowedAddrs { + ctx.GasMeter().ConsumeGas(gasCostPerIteration, "transfer authorization") + if addr == receiver { + return true + } + } + return false +} From 3ffc225c9ab11e015b8cdb2b1fe30dc036907b2c Mon Sep 17 00:00:00 2001 From: Cian Hatton Date: Mon, 9 Jan 2023 16:47:59 +0000 Subject: [PATCH 04/18] chore: renaming transfer_authorization files (#2990) --- .../types/{transfer_authz.go => transfer_authorization.go} | 0 .../{transfer_authz_test.go => transfer_authorization_test.go} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename modules/apps/transfer/types/{transfer_authz.go => transfer_authorization.go} (100%) rename modules/apps/transfer/types/{transfer_authz_test.go => transfer_authorization_test.go} (100%) diff --git a/modules/apps/transfer/types/transfer_authz.go b/modules/apps/transfer/types/transfer_authorization.go similarity index 100% rename from modules/apps/transfer/types/transfer_authz.go rename to modules/apps/transfer/types/transfer_authorization.go diff --git a/modules/apps/transfer/types/transfer_authz_test.go b/modules/apps/transfer/types/transfer_authorization_test.go similarity index 100% rename from modules/apps/transfer/types/transfer_authz_test.go rename to modules/apps/transfer/types/transfer_authorization_test.go From 9a2fe70a23cfdd8958e38a2ede530226be2ac9a1 Mon Sep 17 00:00:00 2001 From: Cian Hatton Date: Mon, 9 Jan 2023 17:15:24 +0000 Subject: [PATCH 05/18] Change ErrDuplicateEntry to ErrInvalidAuthorization & change error formatting (#2988) --- modules/apps/transfer/types/errors.go | 2 +- .../apps/transfer/types/transfer_authorization.go | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/apps/transfer/types/errors.go b/modules/apps/transfer/types/errors.go index 1dcbec14431..d4f85cf4fa7 100644 --- a/modules/apps/transfer/types/errors.go +++ b/modules/apps/transfer/types/errors.go @@ -14,5 +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") + ErrInvalidAuthorization = sdkerrors.Register(ModuleName, 10, "invalid transfer authorization") ) diff --git a/modules/apps/transfer/types/transfer_authorization.go b/modules/apps/transfer/types/transfer_authorization.go index 1baee282b3f..8d0f756eabe 100644 --- a/modules/apps/transfer/types/transfer_authorization.go +++ b/modules/apps/transfer/types/transfer_authorization.go @@ -46,11 +46,11 @@ func (a TransferAuthorization) Accept(ctx sdk.Context, msg sdk.Msg) (authz.Accep if allocation.SourceChannel == msgTransfer.SourceChannel && allocation.SourcePort == msgTransfer.SourcePort { limitLeft, isNegative := allocation.SpendLimit.SafeSub(msgTransfer.Token) if isNegative { - return authz.AcceptResponse{}, sdkerrors.ErrInsufficientFunds.Wrapf("requested amount is more than spend limit") + return authz.AcceptResponse{}, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFunds, "requested amount is more than spend limit") } if !isAllowedAddress(ctx, msgTransfer.Receiver, allocation.AllowedAddresses) { - return authz.AcceptResponse{}, sdkerrors.ErrInvalidAddress.Wrapf("not allowed address for transfer") + return authz.AcceptResponse{}, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "not allowed address for transfer") } if limitLeft.IsZero() { @@ -74,17 +74,17 @@ func (a TransferAuthorization) Accept(ctx sdk.Context, msg sdk.Msg) (authz.Accep }}, nil } } - return authz.AcceptResponse{}, sdkerrors.ErrNotFound.Wrapf("requested port and channel allocation does not exist") + return authz.AcceptResponse{}, sdkerrors.Wrapf(sdkerrors.ErrNotFound, "requested port and channel allocation does not exist") } // ValidateBasic implements Authorization.ValidateBasic. func (a TransferAuthorization) ValidateBasic() error { for _, allocation := range a.Allocations { if allocation.SpendLimit == nil { - return sdkerrors.ErrInvalidCoins.Wrap("spend limit cannot be nil") + return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, "spend limit cannot be nil") } if err := allocation.SpendLimit.Validate(); err != nil { - return sdkerrors.ErrInvalidCoins.Wrapf(err.Error()) + return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, err.Error()) } if err := host.PortIdentifierValidator(allocation.SourcePort); err != nil { return sdkerrors.Wrap(err, "invalid source port ID") @@ -96,7 +96,7 @@ func (a TransferAuthorization) ValidateBasic() error { found := make(map[string]bool, 0) for i := 0; i < len(allocation.AllowedAddresses); i++ { if found[allocation.AllowedAddresses[i]] { - return ErrDuplicateEntry + return sdkerrors.Wrapf(ErrInvalidAuthorization, "duplicate entry in allow list %s") } found[allocation.AllowedAddresses[i]] = true } From 294522546a10ecf993fb35257dc949d5b3bccc60 Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Wed, 11 Jan 2023 11:19:07 +0100 Subject: [PATCH 06/18] chore: rename transfer authz protobuf types (#2989) * moving authz protos to transfer.v1 * running make format * rename allow list and allocation protobuf types * use fully qualified interface name in authz.proto --- modules/apps/transfer/types/authz.pb.go | 141 +++++++++--------- .../transfer/types/transfer_authorization.go | 30 ++-- .../ibc/applications/transfer/v1/authz.proto | 11 +- 3 files changed, 92 insertions(+), 90 deletions(-) diff --git a/modules/apps/transfer/types/authz.pb.go b/modules/apps/transfer/types/authz.pb.go index 403bd32352d..1e81b9968f4 100644 --- a/modules/apps/transfer/types/authz.pb.go +++ b/modules/apps/transfer/types/authz.pb.go @@ -26,29 +26,30 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package -type PortChannelAmount struct { +// Allocation defines the spend limit for a particular port and channel +type Allocation struct { // the port on which the packet will be sent 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 SourceChannel string `protobuf:"bytes,2,opt,name=source_channel,json=sourceChannel,proto3" json:"source_channel,omitempty" yaml:"source_channel"` // spend limitation on the channel SpendLimit github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,3,rep,name=spend_limit,json=spendLimit,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"spend_limit"` - // allowed addresses to be sent via transfer message - AllowedAddresses []string `protobuf:"bytes,4,rep,name=allowed_addresses,json=allowedAddresses,proto3" json:"allowed_addresses,omitempty"` + // allow list of receivers, an empty allow list permits any receiver address + AllowList []string `protobuf:"bytes,4,rep,name=allow_list,json=allowList,proto3" json:"allow_list,omitempty"` } -func (m *PortChannelAmount) Reset() { *m = PortChannelAmount{} } -func (m *PortChannelAmount) String() string { return proto.CompactTextString(m) } -func (*PortChannelAmount) ProtoMessage() {} -func (*PortChannelAmount) Descriptor() ([]byte, []int) { +func (m *Allocation) Reset() { *m = Allocation{} } +func (m *Allocation) String() string { return proto.CompactTextString(m) } +func (*Allocation) ProtoMessage() {} +func (*Allocation) Descriptor() ([]byte, []int) { return fileDescriptor_b1a28b55d17325aa, []int{0} } -func (m *PortChannelAmount) XXX_Unmarshal(b []byte) error { +func (m *Allocation) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } -func (m *PortChannelAmount) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *Allocation) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_PortChannelAmount.Marshal(b, m, deterministic) + return xxx_messageInfo_Allocation.Marshal(b, m, deterministic) } else { b = b[:cap(b)] n, err := m.MarshalToSizedBuffer(b) @@ -58,42 +59,42 @@ func (m *PortChannelAmount) XXX_Marshal(b []byte, deterministic bool) ([]byte, e return b[:n], nil } } -func (m *PortChannelAmount) XXX_Merge(src proto.Message) { - xxx_messageInfo_PortChannelAmount.Merge(m, src) +func (m *Allocation) XXX_Merge(src proto.Message) { + xxx_messageInfo_Allocation.Merge(m, src) } -func (m *PortChannelAmount) XXX_Size() int { +func (m *Allocation) XXX_Size() int { return m.Size() } -func (m *PortChannelAmount) XXX_DiscardUnknown() { - xxx_messageInfo_PortChannelAmount.DiscardUnknown(m) +func (m *Allocation) XXX_DiscardUnknown() { + xxx_messageInfo_Allocation.DiscardUnknown(m) } -var xxx_messageInfo_PortChannelAmount proto.InternalMessageInfo +var xxx_messageInfo_Allocation proto.InternalMessageInfo -func (m *PortChannelAmount) GetSourcePort() string { +func (m *Allocation) GetSourcePort() string { if m != nil { return m.SourcePort } return "" } -func (m *PortChannelAmount) GetSourceChannel() string { +func (m *Allocation) GetSourceChannel() string { if m != nil { return m.SourceChannel } return "" } -func (m *PortChannelAmount) GetSpendLimit() github_com_cosmos_cosmos_sdk_types.Coins { +func (m *Allocation) GetSpendLimit() github_com_cosmos_cosmos_sdk_types.Coins { if m != nil { return m.SpendLimit } return nil } -func (m *PortChannelAmount) GetAllowedAddresses() []string { +func (m *Allocation) GetAllowList() []string { if m != nil { - return m.AllowedAddresses + return m.AllowList } return nil } @@ -102,7 +103,7 @@ func (m *PortChannelAmount) GetAllowedAddresses() []string { // the granter's account for ibc transfer on a specific channel type TransferAuthorization struct { // port and channel amounts - Allocations []PortChannelAmount `protobuf:"bytes,1,rep,name=allocations,proto3" json:"allocations"` + Allocations []Allocation `protobuf:"bytes,1,rep,name=allocations,proto3" json:"allocations"` } func (m *TransferAuthorization) Reset() { *m = TransferAuthorization{} } @@ -138,7 +139,7 @@ func (m *TransferAuthorization) XXX_DiscardUnknown() { var xxx_messageInfo_TransferAuthorization proto.InternalMessageInfo -func (m *TransferAuthorization) GetAllocations() []PortChannelAmount { +func (m *TransferAuthorization) GetAllocations() []Allocation { if m != nil { return m.Allocations } @@ -146,7 +147,7 @@ func (m *TransferAuthorization) GetAllocations() []PortChannelAmount { } func init() { - proto.RegisterType((*PortChannelAmount)(nil), "ibc.applications.transfer.v1.PortChannelAmount") + proto.RegisterType((*Allocation)(nil), "ibc.applications.transfer.v1.Allocation") proto.RegisterType((*TransferAuthorization)(nil), "ibc.applications.transfer.v1.TransferAuthorization") } @@ -155,38 +156,38 @@ func init() { } var fileDescriptor_b1a28b55d17325aa = []byte{ - // 442 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x52, 0xc1, 0x8a, 0x13, 0x31, - 0x18, 0xee, 0x6c, 0x17, 0x61, 0x53, 0x56, 0xec, 0xe0, 0xca, 0x74, 0x91, 0x69, 0x99, 0xd3, 0x80, - 0x34, 0xb1, 0x0a, 0x2e, 0xec, 0xc9, 0x76, 0xaf, 0x1e, 0x74, 0x10, 0x04, 0x2f, 0x25, 0x93, 0x89, - 0x6d, 0x70, 0x26, 0xff, 0x90, 0x64, 0x2a, 0xbb, 0x57, 0x5f, 0xc0, 0xd7, 0xd0, 0xb3, 0x0f, 0xb1, - 0x78, 0xda, 0xa3, 0xa7, 0x2a, 0xed, 0x1b, 0xec, 0x13, 0xc8, 0x24, 0x59, 0xe8, 0x52, 0xf0, 0x34, - 0x93, 0xff, 0xfb, 0xfe, 0x2f, 0xf9, 0xbf, 0xef, 0x47, 0xa9, 0xc8, 0x19, 0xa1, 0x75, 0x5d, 0x0a, - 0x46, 0x8d, 0x00, 0xa9, 0x89, 0x51, 0x54, 0xea, 0x4f, 0x5c, 0x91, 0xd5, 0x84, 0xd0, 0xc6, 0x2c, - 0xaf, 0x70, 0xad, 0xc0, 0x40, 0xf8, 0x54, 0xe4, 0x0c, 0xef, 0x32, 0xf1, 0x1d, 0x13, 0xaf, 0x26, - 0xa7, 0x03, 0x06, 0xba, 0x02, 0x3d, 0xb7, 0x5c, 0xe2, 0x0e, 0xae, 0xf1, 0xf4, 0xf1, 0x02, 0x16, - 0xe0, 0xea, 0xed, 0x9f, 0xaf, 0xc6, 0x8e, 0x43, 0x72, 0xaa, 0x39, 0x59, 0x4d, 0x72, 0x6e, 0xe8, - 0x84, 0x30, 0x10, 0xd2, 0xe1, 0xc9, 0xf7, 0x03, 0xd4, 0x7f, 0x0b, 0xca, 0x5c, 0x2c, 0xa9, 0x94, - 0xbc, 0x9c, 0x56, 0xd0, 0x48, 0x13, 0x9e, 0xa1, 0x9e, 0x86, 0x46, 0x31, 0x3e, 0xaf, 0x41, 0x99, - 0x28, 0x18, 0x05, 0xe9, 0xd1, 0xec, 0xc9, 0xed, 0x7a, 0x18, 0x5e, 0xd2, 0xaa, 0x3c, 0x4f, 0x76, - 0xc0, 0x24, 0x43, 0xee, 0xd4, 0xaa, 0x84, 0xaf, 0xd1, 0x43, 0x8f, 0x31, 0x27, 0x18, 0x1d, 0xd8, - 0xde, 0xc1, 0xed, 0x7a, 0x78, 0x72, 0xaf, 0xd7, 0xe3, 0x49, 0x76, 0xec, 0x0a, 0xfe, 0x01, 0x61, - 0x89, 0x7a, 0xba, 0xe6, 0xb2, 0x98, 0x97, 0xa2, 0x12, 0x26, 0xea, 0x8e, 0xba, 0x69, 0xef, 0xc5, - 0x00, 0xfb, 0x51, 0xdb, 0x31, 0xb0, 0x1f, 0x03, 0x5f, 0x80, 0x90, 0xb3, 0xe7, 0xd7, 0xeb, 0x61, - 0xe7, 0xc7, 0x9f, 0x61, 0xba, 0x10, 0x66, 0xd9, 0xe4, 0x98, 0x41, 0xe5, 0x7d, 0xf1, 0x9f, 0xb1, - 0x2e, 0x3e, 0x13, 0x73, 0x59, 0x73, 0x6d, 0x1b, 0x74, 0x86, 0xac, 0xfe, 0x9b, 0x56, 0x3e, 0x7c, - 0x86, 0xfa, 0xb4, 0x2c, 0xe1, 0x0b, 0x2f, 0xe6, 0xb4, 0x28, 0x14, 0xd7, 0x9a, 0xeb, 0xe8, 0x70, - 0xd4, 0x4d, 0x8f, 0xb2, 0x47, 0x1e, 0x98, 0xde, 0xd5, 0x93, 0xaf, 0x01, 0x3a, 0x79, 0xef, 0xc3, - 0x98, 0x36, 0x66, 0x09, 0x4a, 0x5c, 0xd9, 0x8c, 0xc2, 0x0f, 0xa8, 0xd7, 0xb2, 0x7d, 0x62, 0x51, - 0x60, 0x1f, 0x4d, 0xf0, 0xff, 0xa2, 0xc4, 0x7b, 0xae, 0xcf, 0x0e, 0xdb, 0x51, 0xb2, 0x5d, 0xa5, - 0xf3, 0xfe, 0xaf, 0x9f, 0xe3, 0xe3, 0x7b, 0x77, 0xcd, 0xde, 0x5d, 0x6f, 0xe2, 0xe0, 0x66, 0x13, - 0x07, 0x7f, 0x37, 0x71, 0xf0, 0x6d, 0x1b, 0x77, 0x6e, 0xb6, 0x71, 0xe7, 0xf7, 0x36, 0xee, 0x7c, - 0x3c, 0xdb, 0xb7, 0x40, 0xe4, 0x6c, 0xbc, 0x00, 0xb2, 0x7a, 0x45, 0x2a, 0x28, 0x9a, 0x92, 0xeb, - 0x76, 0x09, 0x77, 0x96, 0xcf, 0xfa, 0x92, 0x3f, 0xb0, 0xbb, 0xf0, 0xf2, 0x5f, 0x00, 0x00, 0x00, - 0xff, 0xff, 0x50, 0xcc, 0x73, 0x94, 0xa6, 0x02, 0x00, 0x00, + // 436 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x52, 0x4d, 0x6e, 0xd3, 0x40, + 0x14, 0x8e, 0x9b, 0x0a, 0x29, 0x13, 0xc1, 0xc2, 0xa2, 0xc8, 0xa9, 0xc0, 0x89, 0xbc, 0x40, 0xde, + 0x64, 0x86, 0x80, 0x44, 0xa5, 0xae, 0x68, 0xba, 0xed, 0xa2, 0x58, 0xac, 0xd8, 0x44, 0xe3, 0xc9, + 0x60, 0x8f, 0x18, 0xfb, 0x59, 0x9e, 0xb1, 0x51, 0x7b, 0x0a, 0x90, 0x38, 0x05, 0x6b, 0x0e, 0x51, + 0xb1, 0xea, 0x92, 0x55, 0x40, 0xc9, 0x0d, 0x7a, 0x02, 0xe4, 0x99, 0x29, 0xb8, 0x42, 0xea, 0xca, + 0x7e, 0x3f, 0xdf, 0x7b, 0xdf, 0xfb, 0xe6, 0x43, 0xb1, 0x48, 0x19, 0xa1, 0x55, 0x25, 0x05, 0xa3, + 0x5a, 0x40, 0xa9, 0x88, 0xae, 0x69, 0xa9, 0x3e, 0xf0, 0x9a, 0xb4, 0x0b, 0x42, 0x1b, 0x9d, 0x5f, + 0xe2, 0xaa, 0x06, 0x0d, 0xfe, 0x53, 0x91, 0x32, 0xdc, 0xef, 0xc4, 0xb7, 0x9d, 0xb8, 0x5d, 0x1c, + 0x4e, 0x18, 0xa8, 0x02, 0xd4, 0xca, 0xf4, 0x12, 0x1b, 0x58, 0xe0, 0xe1, 0xe3, 0x0c, 0x32, 0xb0, + 0xf9, 0xee, 0xcf, 0x65, 0x43, 0xdb, 0x43, 0x52, 0xaa, 0x38, 0x69, 0x17, 0x29, 0xd7, 0x74, 0x41, + 0x18, 0x88, 0xd2, 0xd6, 0xa3, 0xaf, 0x7b, 0x08, 0x9d, 0x48, 0x09, 0x76, 0x99, 0x7f, 0x84, 0xc6, + 0x0a, 0x9a, 0x9a, 0xf1, 0x55, 0x05, 0xb5, 0x0e, 0xbc, 0x99, 0x17, 0x8f, 0x96, 0x4f, 0x6e, 0x36, + 0x53, 0xff, 0x82, 0x16, 0xf2, 0x38, 0xea, 0x15, 0xa3, 0x04, 0xd9, 0xe8, 0x1c, 0x6a, 0xed, 0xbf, + 0x41, 0x8f, 0x5c, 0x8d, 0xe5, 0xb4, 0x2c, 0xb9, 0x0c, 0xf6, 0x0c, 0x76, 0x72, 0xb3, 0x99, 0x1e, + 0xdc, 0xc1, 0xba, 0x7a, 0x94, 0x3c, 0xb4, 0x89, 0x53, 0x1b, 0xfb, 0x12, 0x8d, 0x55, 0xc5, 0xcb, + 0xf5, 0x4a, 0x8a, 0x42, 0xe8, 0x60, 0x38, 0x1b, 0xc6, 0xe3, 0x97, 0x13, 0xec, 0x6e, 0xec, 0xf8, + 0x63, 0xc7, 0x1f, 0x9f, 0x82, 0x28, 0x97, 0x2f, 0xae, 0x36, 0xd3, 0xc1, 0xb7, 0x5f, 0xd3, 0x38, + 0x13, 0x3a, 0x6f, 0x52, 0xcc, 0xa0, 0x70, 0x82, 0xb8, 0xcf, 0x5c, 0xad, 0x3f, 0x12, 0x7d, 0x51, + 0x71, 0x65, 0x00, 0x2a, 0x41, 0x66, 0xfe, 0x59, 0x37, 0xde, 0x7f, 0x86, 0x10, 0x95, 0x12, 0x3e, + 0xad, 0xa4, 0x50, 0x3a, 0xd8, 0x9f, 0x0d, 0xe3, 0x51, 0x32, 0x32, 0x99, 0x33, 0xa1, 0x74, 0xf4, + 0xc5, 0x43, 0x07, 0xef, 0x9c, 0xee, 0x27, 0x8d, 0xce, 0xa1, 0x16, 0x97, 0x56, 0xa1, 0x73, 0x34, + 0xa6, 0x7f, 0xf5, 0x52, 0x81, 0x67, 0x68, 0xc6, 0xf8, 0xbe, 0x57, 0xc3, 0xff, 0x04, 0x5e, 0xee, + 0x77, 0xac, 0x93, 0xfe, 0x88, 0xe3, 0xe7, 0x3f, 0xbe, 0xcf, 0x23, 0x77, 0xa6, 0x75, 0xc2, 0xed, + 0x9d, 0x77, 0x36, 0x2f, 0xdf, 0x5e, 0x6d, 0x43, 0xef, 0x7a, 0x1b, 0x7a, 0xbf, 0xb7, 0xa1, 0xf7, + 0x79, 0x17, 0x0e, 0xae, 0x77, 0xe1, 0xe0, 0xe7, 0x2e, 0x1c, 0xbc, 0x3f, 0xfa, 0x5f, 0x02, 0x91, + 0xb2, 0x79, 0x06, 0xa4, 0x7d, 0x4d, 0x0a, 0x58, 0x37, 0x92, 0xab, 0xce, 0x7d, 0x3d, 0xd7, 0x19, + 0x5d, 0xd2, 0x07, 0xc6, 0x04, 0xaf, 0xfe, 0x04, 0x00, 0x00, 0xff, 0xff, 0x7e, 0xff, 0x95, 0x1c, + 0x9f, 0x02, 0x00, 0x00, } -func (m *PortChannelAmount) Marshal() (dAtA []byte, err error) { +func (m *Allocation) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -196,21 +197,21 @@ func (m *PortChannelAmount) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *PortChannelAmount) MarshalTo(dAtA []byte) (int, error) { +func (m *Allocation) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *PortChannelAmount) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *Allocation) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - if len(m.AllowedAddresses) > 0 { - for iNdEx := len(m.AllowedAddresses) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.AllowedAddresses[iNdEx]) - copy(dAtA[i:], m.AllowedAddresses[iNdEx]) - i = encodeVarintAuthz(dAtA, i, uint64(len(m.AllowedAddresses[iNdEx]))) + if len(m.AllowList) > 0 { + for iNdEx := len(m.AllowList) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.AllowList[iNdEx]) + copy(dAtA[i:], m.AllowList[iNdEx]) + i = encodeVarintAuthz(dAtA, i, uint64(len(m.AllowList[iNdEx]))) i-- dAtA[i] = 0x22 } @@ -294,7 +295,7 @@ func encodeVarintAuthz(dAtA []byte, offset int, v uint64) int { dAtA[offset] = uint8(v) return base } -func (m *PortChannelAmount) Size() (n int) { +func (m *Allocation) Size() (n int) { if m == nil { return 0 } @@ -314,8 +315,8 @@ func (m *PortChannelAmount) Size() (n int) { n += 1 + l + sovAuthz(uint64(l)) } } - if len(m.AllowedAddresses) > 0 { - for _, s := range m.AllowedAddresses { + if len(m.AllowList) > 0 { + for _, s := range m.AllowList { l = len(s) n += 1 + l + sovAuthz(uint64(l)) } @@ -344,7 +345,7 @@ func sovAuthz(x uint64) (n int) { func sozAuthz(x uint64) (n int) { return sovAuthz(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } -func (m *PortChannelAmount) Unmarshal(dAtA []byte) error { +func (m *Allocation) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -367,10 +368,10 @@ func (m *PortChannelAmount) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: PortChannelAmount: wiretype end group for non-group") + return fmt.Errorf("proto: Allocation: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: PortChannelAmount: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: Allocation: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -473,7 +474,7 @@ func (m *PortChannelAmount) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 4: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field AllowedAddresses", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field AllowList", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -501,7 +502,7 @@ func (m *PortChannelAmount) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.AllowedAddresses = append(m.AllowedAddresses, string(dAtA[iNdEx:postIndex])) + m.AllowList = append(m.AllowList, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex default: iNdEx = preIndex @@ -582,7 +583,7 @@ func (m *TransferAuthorization) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Allocations = append(m.Allocations, PortChannelAmount{}) + m.Allocations = append(m.Allocations, Allocation{}) if err := m.Allocations[len(m.Allocations)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } diff --git a/modules/apps/transfer/types/transfer_authorization.go b/modules/apps/transfer/types/transfer_authorization.go index 8d0f756eabe..743b86623a0 100644 --- a/modules/apps/transfer/types/transfer_authorization.go +++ b/modules/apps/transfer/types/transfer_authorization.go @@ -16,13 +16,13 @@ var _ authz.Authorization = &TransferAuthorization{} // NewTransferAuthorization creates a new TransferAuthorization object. func NewTransferAuthorization(sourcePorts, sourceChannels []string, spendLimits []sdk.Coins, allowedAddrs [][]string) *TransferAuthorization { - allocations := []PortChannelAmount{} + allocations := []Allocation{} for index := range sourcePorts { - allocations = append(allocations, PortChannelAmount{ - SourcePort: sourcePorts[index], - SourceChannel: sourceChannels[index], - SpendLimit: spendLimits[index], - AllowedAddresses: allowedAddrs[index], + allocations = append(allocations, Allocation{ + SourcePort: sourcePorts[index], + SourceChannel: sourceChannels[index], + SpendLimit: spendLimits[index], + AllowList: allowedAddrs[index], }) } return &TransferAuthorization{ @@ -49,7 +49,7 @@ func (a TransferAuthorization) Accept(ctx sdk.Context, msg sdk.Msg) (authz.Accep return authz.AcceptResponse{}, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFunds, "requested amount is more than spend limit") } - if !isAllowedAddress(ctx, msgTransfer.Receiver, allocation.AllowedAddresses) { + if !isAllowedAddress(ctx, msgTransfer.Receiver, allocation.AllowList) { return authz.AcceptResponse{}, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "not allowed address for transfer") } @@ -62,11 +62,11 @@ func (a TransferAuthorization) Accept(ctx sdk.Context, msg sdk.Msg) (authz.Accep Allocations: a.Allocations, }}, nil } - a.Allocations[index] = PortChannelAmount{ - SourcePort: allocation.SourcePort, - SourceChannel: allocation.SourceChannel, - SpendLimit: limitLeft, - AllowedAddresses: allocation.AllowedAddresses, + a.Allocations[index] = Allocation{ + SourcePort: allocation.SourcePort, + SourceChannel: allocation.SourceChannel, + SpendLimit: limitLeft, + AllowList: allocation.AllowList, } return authz.AcceptResponse{Accept: true, Delete: false, Updated: &TransferAuthorization{ @@ -94,11 +94,11 @@ func (a TransferAuthorization) ValidateBasic() error { } found := make(map[string]bool, 0) - for i := 0; i < len(allocation.AllowedAddresses); i++ { - if found[allocation.AllowedAddresses[i]] { + for i := 0; i < len(allocation.AllowList); i++ { + if found[allocation.AllowList[i]] { return sdkerrors.Wrapf(ErrInvalidAuthorization, "duplicate entry in allow list %s") } - found[allocation.AllowedAddresses[i]] = true + found[allocation.AllowList[i]] = true } } return nil diff --git a/proto/ibc/applications/transfer/v1/authz.proto b/proto/ibc/applications/transfer/v1/authz.proto index b1aa9b2adb1..53113bf5e11 100644 --- a/proto/ibc/applications/transfer/v1/authz.proto +++ b/proto/ibc/applications/transfer/v1/authz.proto @@ -8,7 +8,8 @@ import "cosmos_proto/cosmos.proto"; import "gogoproto/gogo.proto"; import "cosmos/base/v1beta1/coin.proto"; -message PortChannelAmount { +// Allocation defines the spend limit for a particular port and channel +message Allocation { // the port on which the packet will be sent string source_port = 1 [(gogoproto.moretags) = "yaml:\"source_port\""]; // the channel by which the packet will be sent @@ -16,15 +17,15 @@ message PortChannelAmount { // spend limitation on the channel 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; + // allow list of receivers, an empty allow list permits any receiver address + repeated string allow_list = 4; } // TransferAuthorization allows the grantee to spend up to spend_limit coins from // the granter's account for ibc transfer on a specific channel message TransferAuthorization { - option (cosmos_proto.implements_interface) = "Authorization"; + option (cosmos_proto.implements_interface) = "cosmos.authz.v1beta1.Authorization"; // port and channel amounts - repeated PortChannelAmount allocations = 1 [(gogoproto.nullable) = false]; + repeated Allocation allocations = 1 [(gogoproto.nullable) = false]; } From f9be376fa0115be596f0ecd26d8d36f86a39407f Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Wed, 11 Jan 2023 11:33:53 +0100 Subject: [PATCH 07/18] chore: refactor NewTransferAuthorization constructor to use varargs (#2991) * moving authz protos to transfer.v1 * running make format * rename allow list and allocation protobuf types * refactoring NewTransferAuthorization constructor func to use varargs --- .../transfer/types/transfer_authorization.go | 11 +--- .../types/transfer_authorization_test.go | 58 +++++++++++++++---- 2 files changed, 48 insertions(+), 21 deletions(-) diff --git a/modules/apps/transfer/types/transfer_authorization.go b/modules/apps/transfer/types/transfer_authorization.go index 743b86623a0..20eb1856cc7 100644 --- a/modules/apps/transfer/types/transfer_authorization.go +++ b/modules/apps/transfer/types/transfer_authorization.go @@ -15,16 +15,7 @@ const gasCostPerIteration = uint64(10) var _ authz.Authorization = &TransferAuthorization{} // NewTransferAuthorization creates a new TransferAuthorization object. -func NewTransferAuthorization(sourcePorts, sourceChannels []string, spendLimits []sdk.Coins, allowedAddrs [][]string) *TransferAuthorization { - allocations := []Allocation{} - for index := range sourcePorts { - allocations = append(allocations, Allocation{ - SourcePort: sourcePorts[index], - SourceChannel: sourceChannels[index], - SpendLimit: spendLimits[index], - AllowList: allowedAddrs[index], - }) - } +func NewTransferAuthorization(allocations ...Allocation) *TransferAuthorization { return &TransferAuthorization{ Allocations: allocations, } diff --git a/modules/apps/transfer/types/transfer_authorization_test.go b/modules/apps/transfer/types/transfer_authorization_test.go index 873303d7e7a..35989524722 100644 --- a/modules/apps/transfer/types/transfer_authorization_test.go +++ b/modules/apps/transfer/types/transfer_authorization_test.go @@ -26,7 +26,13 @@ var ( func TestTransferAuthorization(t *testing.T) { app := simapp.Setup(t, false) ctx := app.BaseApp.NewContext(false, tmproto.Header{}) - authorization := NewTransferAuthorization([]string{sourcePort}, []string{sourceChannel}, []sdk.Coins{coins1000}, [][]string{{toAddr.String()}}) + allocation := Allocation{ + SourcePort: sourcePort, + SourceChannel: sourceChannel, + SpendLimit: coins1000, + AllowList: []string{toAddr.String()}, + } + authorization := NewTransferAuthorization(allocation) t.Log("verify authorization returns valid method name") require.Equal(t, authorization.MsgTypeURL(), "/ibc.applications.transfer.v1.MsgTransfer") @@ -41,7 +47,7 @@ func TestTransferAuthorization(t *testing.T) { require.Nil(t, resp.Updated) t.Log("verify updated authorization returns remaining spent limit") - authorization = NewTransferAuthorization([]string{sourcePort}, []string{sourceChannel}, []sdk.Coins{coins1000}, [][]string{{toAddr.String()}}) + authorization = NewTransferAuthorization(allocation) require.Equal(t, authorization.MsgTypeURL(), "/ibc.applications.transfer.v1.MsgTransfer") require.NoError(t, authorization.ValidateBasic()) transfer = NewMsgTransfer(sourcePort, sourceChannel, coin500, fromAddr.String(), toAddr.String(), timeoutHeight, 0, "") @@ -50,7 +56,14 @@ func TestTransferAuthorization(t *testing.T) { require.NoError(t, err) require.False(t, resp.Delete) require.NotNil(t, resp.Updated) - sendAuth := NewTransferAuthorization([]string{sourcePort}, []string{sourceChannel}, []sdk.Coins{coins500}, [][]string{{toAddr.String()}}) + + allocation = Allocation{ + SourcePort: sourcePort, + SourceChannel: sourceChannel, + SpendLimit: coins500, + AllowList: []string{toAddr.String()}, + } + sendAuth := NewTransferAuthorization(allocation) require.Equal(t, sendAuth.String(), resp.Updated.String()) t.Log("expect updated authorization nil after spending remaining amount") @@ -60,26 +73,49 @@ func TestTransferAuthorization(t *testing.T) { require.Nil(t, resp.Updated) t.Log("expect error when spend limit for specific port and channel is not set") - authorization = NewTransferAuthorization([]string{sourcePort}, []string{sourceChannel}, []sdk.Coins{coins1000}, [][]string{{toAddr.String()}}) + allocation = Allocation{ + SourcePort: sourcePort, + SourceChannel: sourceChannel, + SpendLimit: coins1000, + AllowList: []string{toAddr.String()}, + } + authorization = NewTransferAuthorization(allocation) transfer = NewMsgTransfer(sourcePort2, sourceChannel2, coin500, fromAddr.String(), toAddr.String(), timeoutHeight, 0, "") _, err = authorization.Accept(ctx, transfer) require.Error(t, err) t.Log("expect removing only 1 allocation if spend limit is finalized for the port") - authorization = NewTransferAuthorization( - []string{sourcePort, sourcePort2}, - []string{sourceChannel, sourceChannel2}, - []sdk.Coins{coins1000, coins1000}, - [][]string{{toAddr.String()}, {toAddr.String()}}) + + allocations := []Allocation{ + { + SourcePort: sourcePort, + SourceChannel: sourceChannel, + SpendLimit: coins1000, + AllowList: []string{toAddr.String()}, + }, + { + SourcePort: sourcePort2, + SourceChannel: sourceChannel2, + SpendLimit: coins1000, + AllowList: []string{toAddr.String()}, + }, + } + authorization = NewTransferAuthorization(allocations...) transfer = NewMsgTransfer(sourcePort, sourceChannel, coin1000, fromAddr.String(), toAddr.String(), timeoutHeight, 0, "") resp, err = authorization.Accept(ctx, transfer) require.NoError(t, err) require.NotNil(t, resp.Updated) - require.Equal(t, resp.Updated, NewTransferAuthorization([]string{sourcePort2}, []string{sourceChannel2}, []sdk.Coins{coins1000}, [][]string{{toAddr.String()}})) + require.Equal(t, resp.Updated, NewTransferAuthorization(allocations[1])) require.False(t, resp.Delete) t.Log("expect error when transferring to not allowed address") - authorization = NewTransferAuthorization([]string{sourcePort}, []string{sourceChannel}, []sdk.Coins{coins1000}, [][]string{{fromAddr.String()}}) + allocation = Allocation{ + SourcePort: sourcePort, + SourceChannel: sourceChannel, + SpendLimit: coins1000, + AllowList: []string{fromAddr.String()}, + } + authorization = NewTransferAuthorization(allocation) transfer = NewMsgTransfer(sourcePort, sourceChannel, coin500, fromAddr.String(), toAddr.String(), timeoutHeight, 0, "") _, err = authorization.Accept(ctx, transfer) require.Error(t, err) From aabb07a12457b35b9b28493311a9278639dd529b Mon Sep 17 00:00:00 2001 From: Cian Hatton Date: Wed, 11 Jan 2023 16:59:22 +0000 Subject: [PATCH 08/18] e2e: added happy path e2e test for ICS20 authz integration (#2996) --- .github/workflows/e2e-manual-simd.yaml | 1 + e2e/testconfig/testconfig.go | 8 ++ e2e/tests/transfer/authz_test.go | 156 +++++++++++++++++++++++++ e2e/testsuite/codec.go | 4 + e2e/testsuite/testsuite.go | 30 ++++- 5 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 e2e/tests/transfer/authz_test.go diff --git a/.github/workflows/e2e-manual-simd.yaml b/.github/workflows/e2e-manual-simd.yaml index 76bf85c6e2d..58d3fd0f3c6 100644 --- a/.github/workflows/e2e-manual-simd.yaml +++ b/.github/workflows/e2e-manual-simd.yaml @@ -17,6 +17,7 @@ on: - TestInterchainAccountsGroupsTestSuite - TestInterchainAccountsGovTestSuite - TestIncentivizedInterchainAccountsTestSuite + - TestAuthzTransferTestSuite chain-image: description: 'The image to use for chain A' required: true diff --git a/e2e/testconfig/testconfig.go b/e2e/testconfig/testconfig.go index d4cb5eab329..84451f109ab 100644 --- a/e2e/testconfig/testconfig.go +++ b/e2e/testconfig/testconfig.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "os" + "strings" "github.com/cosmos/cosmos-sdk/codec" simappparams "github.com/cosmos/cosmos-sdk/simapp/params" @@ -129,6 +130,13 @@ func GetChainBTag() string { return chainBTag } +// IsCI returns true if the tests are running in CI, false is returned +// if the tests are running locally. +// Note: github actions passes a CI env value of true by default to all runners. +func IsCI() bool { + return strings.ToLower(os.Getenv("CI")) == "true" +} + // ChainOptions stores chain configurations for the chains that will be // created for the tests. They can be modified by passing ChainOptionConfiguration // to E2ETestSuite.GetChains. diff --git a/e2e/tests/transfer/authz_test.go b/e2e/tests/transfer/authz_test.go new file mode 100644 index 00000000000..4da10d7d523 --- /dev/null +++ b/e2e/tests/transfer/authz_test.go @@ -0,0 +1,156 @@ +package transfer + +import ( + "context" + "testing" + + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/authz" + test "github.com/strangelove-ventures/ibctest/v6/testutil" + "github.com/stretchr/testify/suite" + + "github.com/cosmos/ibc-go/e2e/testsuite" + "github.com/cosmos/ibc-go/e2e/testvalues" + transfertypes "github.com/cosmos/ibc-go/v6/modules/apps/transfer/types" +) + +func TestAuthzTransferTestSuite(t *testing.T) { + suite.Run(t, new(AuthzTransferTestSuite)) +} + +type AuthzTransferTestSuite struct { + testsuite.E2ETestSuite +} + +func (suite *AuthzTransferTestSuite) TestAuthz_MsgTransfer_Succeeds() { + t := suite.T() + ctx := context.TODO() + + relayer, channelA := suite.SetupChainsRelayerAndChannel(ctx, transferChannelOptions()) + chainA, chainB := suite.GetChains() + + chainADenom := chainA.Config().Denom + + granterWallet := suite.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) + granterAddress := granterWallet.Bech32Address(chainA.Config().Bech32Prefix) + + granteeWallet := suite.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) + granteeAddress := granteeWallet.Bech32Address(chainA.Config().Bech32Prefix) + + receiverWallet := suite.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount) + receiverWalletAddress := receiverWallet.Bech32Address(chainB.Config().Bech32Prefix) + + t.Run("start relayer", func(t *testing.T) { + suite.StartRelayer(relayer) + }) + + // createMsgGrantFn initializes a TransferAuthorization and broadcasts a MsgGrant message. + createMsgGrantFn := func(t *testing.T) { + transferAuth := transfertypes.TransferAuthorization{ + Allocations: []transfertypes.Allocation{ + { + SourcePort: channelA.PortID, + SourceChannel: channelA.ChannelID, + SpendLimit: sdk.NewCoins(sdk.NewCoin(chainADenom, sdk.NewInt(testvalues.StartingTokenAmount))), + AllowList: []string{receiverWalletAddress}, + }, + }, + } + + authAny, err := codectypes.NewAnyWithValue(&transferAuth) + suite.Require().NoError(err) + + msgGrant := &authz.MsgGrant{ + Granter: granterAddress, + Grantee: granteeAddress, + Grant: authz.Grant{ + Authorization: authAny, + // no expiration + Expiration: nil, + }, + } + + resp, err := suite.BroadcastMessages(context.TODO(), chainA, granterWallet, msgGrant) + suite.AssertValidTxResponse(resp) + suite.Require().NoError(err) + } + + // verifyGrantFn returns a test function which asserts chainA has a grant authorization + // with the given spend limit. + verifyGrantFn := func(expectedLimit int64) func(t *testing.T) { + return func(t *testing.T) { + grantAuths, err := suite.QueryGranterGrants(ctx, chainA, granterAddress) + + suite.Require().NoError(err) + suite.Require().Len(grantAuths, 1) + grantAuthorization := grantAuths[0] + + transferAuth := suite.extractTransferAuthorizationFromGrantAuthorization(grantAuthorization) + expectedSpendLimit := sdk.NewCoins(sdk.NewCoin(chainADenom, sdk.NewInt(expectedLimit))) + suite.Require().Equal(expectedSpendLimit, transferAuth.Allocations[0].SpendLimit) + } + } + + t.Run("broadcast MsgGrant", createMsgGrantFn) + + t.Run("broadcast MsgExec for ibc MsgTransfer", func(t *testing.T) { + transferMsg := transfertypes.MsgTransfer{ + SourcePort: channelA.PortID, + SourceChannel: channelA.ChannelID, + Token: testvalues.DefaultTransferAmount(chainADenom), + Sender: granterAddress, + Receiver: receiverWalletAddress, + TimeoutHeight: suite.GetTimeoutHeight(ctx, chainB), + } + + transferAny, err := codectypes.NewAnyWithValue(&transferMsg) + suite.Require().NoError(err) + + msgExec := &authz.MsgExec{ + Grantee: granteeAddress, + Msgs: []*codectypes.Any{transferAny}, + } + + resp, err := suite.BroadcastMessages(context.TODO(), chainA, granteeWallet, msgExec) + suite.AssertValidTxResponse(resp) + suite.Require().NoError(err) + }) + + t.Run("verify granter wallet amount", func(t *testing.T) { + actualBalance, err := suite.GetChainANativeBalance(ctx, granterWallet) + suite.Require().NoError(err) + + expected := testvalues.StartingTokenAmount - testvalues.IBCTransferAmount + suite.Require().Equal(expected, actualBalance) + }) + + suite.Require().NoError(test.WaitForBlocks(context.TODO(), 10, chainB)) + + t.Run("verify receiver wallet amount", func(t *testing.T) { + chainBIBCToken := testsuite.GetIBCToken(chainADenom, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID) + actualBalance, err := chainB.GetBalance(ctx, receiverWalletAddress, chainBIBCToken.IBCDenom()) + suite.Require().NoError(err) + suite.Require().Equal(testvalues.IBCTransferAmount, actualBalance) + }) + + t.Run("granter grant spend limit reduced", verifyGrantFn(testvalues.StartingTokenAmount-testvalues.IBCTransferAmount)) + + t.Run("re-initialize MsgGrant", createMsgGrantFn) + + t.Run("granter grant was reinitialized", verifyGrantFn(testvalues.StartingTokenAmount)) + +} + +// extractTransferAuthorizationFromGrantAuthorization extracts a TransferAuthorization from the given +// GrantAuthorization. +func (suite *AuthzTransferTestSuite) extractTransferAuthorizationFromGrantAuthorization(grantAuth *authz.GrantAuthorization) *transfertypes.TransferAuthorization { + cfg := testsuite.EncodingConfig() + var authorization authz.Authorization + err := cfg.InterfaceRegistry.UnpackAny(grantAuth.Authorization, &authorization) + suite.Require().NoError(err) + + transferAuth, ok := authorization.(*transfertypes.TransferAuthorization) + suite.Require().True(ok) + return transferAuth +} diff --git a/e2e/testsuite/codec.go b/e2e/testsuite/codec.go index dcee96ced4f..4181ef2ff0f 100644 --- a/e2e/testsuite/codec.go +++ b/e2e/testsuite/codec.go @@ -3,9 +3,11 @@ package testsuite import ( "github.com/cosmos/cosmos-sdk/codec" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/authz" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" + transfertypes "github.com/cosmos/ibc-go/v6/modules/apps/transfer/types" simappparams "github.com/cosmos/ibc-go/v6/testing/simapp/params" ) @@ -24,6 +26,8 @@ func codecAndEncodingConfig() (*codec.ProtoCodec, simappparams.EncodingConfig) { banktypes.RegisterInterfaces(cfg.InterfaceRegistry) govv1beta1.RegisterInterfaces(cfg.InterfaceRegistry) authtypes.RegisterInterfaces(cfg.InterfaceRegistry) + authz.RegisterInterfaces(cfg.InterfaceRegistry) + transfertypes.RegisterInterfaces(cfg.InterfaceRegistry) cdc := codec.NewProtoCodec(cfg.InterfaceRegistry) return cdc, cfg } diff --git a/e2e/testsuite/testsuite.go b/e2e/testsuite/testsuite.go index b8c03f0e5f8..c2fb576d442 100644 --- a/e2e/testsuite/testsuite.go +++ b/e2e/testsuite/testsuite.go @@ -11,6 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/tx" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/authz" govtypesv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" govtypesv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" grouptypes "github.com/cosmos/cosmos-sdk/x/group" @@ -81,6 +82,7 @@ type GRPCClients struct { GroupsQueryClient grouptypes.QueryClient ParamsQueryClient paramsproposaltypes.QueryClient AuthQueryClient authtypes.QueryClient + AuthZQueryClient authz.QueryClient } // path is a pairing of two chains which will be used in a test. @@ -391,6 +393,7 @@ func (s *E2ETestSuite) InitGRPCClients(chain *cosmos.CosmosChain) { GroupsQueryClient: grouptypes.NewQueryClient(grpcConn), ParamsQueryClient: paramsproposaltypes.NewQueryClient(grpcConn), AuthQueryClient: authtypes.NewQueryClient(grpcConn), + AuthZQueryClient: authz.NewQueryClient(grpcConn), } } @@ -425,7 +428,7 @@ func (s *E2ETestSuite) createCosmosChains(chainOptions testconfig.ChainOptions) logger := zaptest.NewLogger(s.T()) - numValidators, numFullNodes := 4, 1 + numValidators, numFullNodes := getValidatorsAndFullNodes() chainA := cosmos.NewCosmosChain(s.T().Name(), *chainOptions.ChainAConfig, numValidators, numFullNodes, logger) chainB := cosmos.NewCosmosChain(s.T().Name(), *chainOptions.ChainBConfig, numValidators, numFullNodes, logger) @@ -539,7 +542,32 @@ func (s *E2ETestSuite) QueryModuleAccountAddress(ctx context.Context, moduleName return moduleAccount.GetAddress(), nil } +// QueryGranterGrants returns all GrantAuthorizations for the given granterAddress. +func (s *E2ETestSuite) QueryGranterGrants(ctx context.Context, chain *cosmos.CosmosChain, granterAddress string) ([]*authz.GrantAuthorization, error) { + authzClient := s.GetChainGRCPClients(chain).AuthZQueryClient + queryRequest := &authz.QueryGranterGrantsRequest{ + Granter: granterAddress, + } + + grants, err := authzClient.GranterGrants(ctx, queryRequest) + if err != nil { + return nil, err + } + + return grants.Grants, nil +} + // GetIBCToken returns the denomination of the full token denom sent to the receiving channel func GetIBCToken(fullTokenDenom string, portID, channelID string) transfertypes.DenomTrace { return transfertypes.ParseDenomTrace(fmt.Sprintf("%s/%s/%s", portID, channelID, fullTokenDenom)) } + +// getValidatorsAndFullNodes returns the number of validators and full nodes respectively that should be used for +// the test. If the test is running in CI, more nodes are used, when running locally a single node is used to +// use less resources and allow the tests to run faster. +func getValidatorsAndFullNodes() (int, int) { + if testconfig.IsCI() { + return 4, 1 + } + return 1, 0 +} From a1e84c999a1993a02c165bcac0f4c483a8fb6dec Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Thu, 12 Jan 2023 09:50:23 +0100 Subject: [PATCH 09/18] chore: implement transfer authz ValidateBasic tests (#2992) * moving authz protos to transfer.v1 * running make format * rename allow list and allocation protobuf types * use fully qualified interface name in authz.proto * adding validate basic tests * if allow list is empty, permit any receiver * test formatting --- .../transfer/types/transfer_authorization.go | 12 ++ .../types/transfer_authorization_test.go | 152 +++++++++++++++--- 2 files changed, 146 insertions(+), 18 deletions(-) diff --git a/modules/apps/transfer/types/transfer_authorization.go b/modules/apps/transfer/types/transfer_authorization.go index 20eb1856cc7..8b0a9fc56cf 100644 --- a/modules/apps/transfer/types/transfer_authorization.go +++ b/modules/apps/transfer/types/transfer_authorization.go @@ -70,16 +70,23 @@ func (a TransferAuthorization) Accept(ctx sdk.Context, msg sdk.Msg) (authz.Accep // ValidateBasic implements Authorization.ValidateBasic. func (a TransferAuthorization) ValidateBasic() error { + if len(a.Allocations) == 0 { + return sdkerrors.Wrap(ErrInvalidAuthorization, "allocations cannot be empty") + } + for _, allocation := range a.Allocations { if allocation.SpendLimit == nil { return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, "spend limit cannot be nil") } + if err := allocation.SpendLimit.Validate(); err != nil { return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, err.Error()) } + if err := host.PortIdentifierValidator(allocation.SourcePort); err != nil { return sdkerrors.Wrap(err, "invalid source port ID") } + if err := host.ChannelIdentifierValidator(allocation.SourceChannel); err != nil { return sdkerrors.Wrap(err, "invalid source channel ID") } @@ -92,12 +99,17 @@ func (a TransferAuthorization) ValidateBasic() error { found[allocation.AllowList[i]] = true } } + return nil } // isAllowedAddress returns a boolean indicating if the receiver address is valid for transfer. // gasCostPerIteration gas is consumed for each iteration. func isAllowedAddress(ctx sdk.Context, receiver string, allowedAddrs []string) bool { + if len(allowedAddrs) == 0 { + return true + } + for _, addr := range allowedAddrs { ctx.GasMeter().ConsumeGas(gasCostPerIteration, "transfer authorization") if addr == receiver { diff --git a/modules/apps/transfer/types/transfer_authorization_test.go b/modules/apps/transfer/types/transfer_authorization_test.go index 35989524722..d1c6cc7fb12 100644 --- a/modules/apps/transfer/types/transfer_authorization_test.go +++ b/modules/apps/transfer/types/transfer_authorization_test.go @@ -1,4 +1,4 @@ -package types +package types_test import ( "testing" @@ -8,6 +8,10 @@ import ( "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/ibc-go/v6/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v6/modules/core/02-client/types" + ibctesting "github.com/cosmos/ibc-go/v6/testing" + "github.com/cosmos/ibc-go/v6/testing/mock" ) var ( @@ -21,23 +25,24 @@ var ( coin500 = sdk.NewCoin("stake", sdk.NewInt(500)) fromAddr = sdk.AccAddress("_____from _____") toAddr = sdk.AccAddress("_______to________") + timeoutHeight = clienttypes.NewHeight(0, 10) ) func TestTransferAuthorization(t *testing.T) { app := simapp.Setup(t, false) ctx := app.BaseApp.NewContext(false, tmproto.Header{}) - allocation := Allocation{ + allocation := types.Allocation{ SourcePort: sourcePort, SourceChannel: sourceChannel, SpendLimit: coins1000, AllowList: []string{toAddr.String()}, } - authorization := NewTransferAuthorization(allocation) + authorization := types.NewTransferAuthorization(allocation) t.Log("verify authorization returns valid method name") require.Equal(t, authorization.MsgTypeURL(), "/ibc.applications.transfer.v1.MsgTransfer") require.NoError(t, authorization.ValidateBasic()) - transfer := NewMsgTransfer(sourcePort, sourceChannel, coin1000, fromAddr.String(), toAddr.String(), timeoutHeight, 0, "") + transfer := types.NewMsgTransfer(sourcePort, sourceChannel, coin1000, fromAddr.String(), toAddr.String(), timeoutHeight, 0, "") require.NoError(t, authorization.ValidateBasic()) t.Log("verify updated authorization returns nil") @@ -47,23 +52,23 @@ func TestTransferAuthorization(t *testing.T) { require.Nil(t, resp.Updated) t.Log("verify updated authorization returns remaining spent limit") - authorization = NewTransferAuthorization(allocation) + authorization = types.NewTransferAuthorization(allocation) require.Equal(t, authorization.MsgTypeURL(), "/ibc.applications.transfer.v1.MsgTransfer") require.NoError(t, authorization.ValidateBasic()) - transfer = NewMsgTransfer(sourcePort, sourceChannel, coin500, fromAddr.String(), toAddr.String(), timeoutHeight, 0, "") + transfer = types.NewMsgTransfer(sourcePort, sourceChannel, coin500, fromAddr.String(), toAddr.String(), timeoutHeight, 0, "") require.NoError(t, authorization.ValidateBasic()) resp, err = authorization.Accept(ctx, transfer) require.NoError(t, err) require.False(t, resp.Delete) require.NotNil(t, resp.Updated) - allocation = Allocation{ + allocation = types.Allocation{ SourcePort: sourcePort, SourceChannel: sourceChannel, SpendLimit: coins500, AllowList: []string{toAddr.String()}, } - sendAuth := NewTransferAuthorization(allocation) + sendAuth := types.NewTransferAuthorization(allocation) require.Equal(t, sendAuth.String(), resp.Updated.String()) t.Log("expect updated authorization nil after spending remaining amount") @@ -73,20 +78,20 @@ func TestTransferAuthorization(t *testing.T) { require.Nil(t, resp.Updated) t.Log("expect error when spend limit for specific port and channel is not set") - allocation = Allocation{ + allocation = types.Allocation{ SourcePort: sourcePort, SourceChannel: sourceChannel, SpendLimit: coins1000, AllowList: []string{toAddr.String()}, } - authorization = NewTransferAuthorization(allocation) - transfer = NewMsgTransfer(sourcePort2, sourceChannel2, coin500, fromAddr.String(), toAddr.String(), timeoutHeight, 0, "") + authorization = types.NewTransferAuthorization(allocation) + transfer = types.NewMsgTransfer(sourcePort2, sourceChannel2, coin500, fromAddr.String(), toAddr.String(), timeoutHeight, 0, "") _, err = authorization.Accept(ctx, transfer) require.Error(t, err) t.Log("expect removing only 1 allocation if spend limit is finalized for the port") - allocations := []Allocation{ + allocations := []types.Allocation{ { SourcePort: sourcePort, SourceChannel: sourceChannel, @@ -100,23 +105,134 @@ func TestTransferAuthorization(t *testing.T) { AllowList: []string{toAddr.String()}, }, } - authorization = NewTransferAuthorization(allocations...) - transfer = NewMsgTransfer(sourcePort, sourceChannel, coin1000, fromAddr.String(), toAddr.String(), timeoutHeight, 0, "") + authorization = types.NewTransferAuthorization(allocations...) + transfer = types.NewMsgTransfer(sourcePort, sourceChannel, coin1000, fromAddr.String(), toAddr.String(), timeoutHeight, 0, "") resp, err = authorization.Accept(ctx, transfer) require.NoError(t, err) require.NotNil(t, resp.Updated) - require.Equal(t, resp.Updated, NewTransferAuthorization(allocations[1])) + require.Equal(t, resp.Updated, types.NewTransferAuthorization(allocations[1])) require.False(t, resp.Delete) t.Log("expect error when transferring to not allowed address") - allocation = Allocation{ + allocation = types.Allocation{ SourcePort: sourcePort, SourceChannel: sourceChannel, SpendLimit: coins1000, AllowList: []string{fromAddr.String()}, } - authorization = NewTransferAuthorization(allocation) - transfer = NewMsgTransfer(sourcePort, sourceChannel, coin500, fromAddr.String(), toAddr.String(), timeoutHeight, 0, "") + authorization = types.NewTransferAuthorization(allocation) + transfer = types.NewMsgTransfer(sourcePort, sourceChannel, coin500, fromAddr.String(), toAddr.String(), timeoutHeight, 0, "") _, err = authorization.Accept(ctx, transfer) require.Error(t, err) } + +func TestTransferAuthorizationValidateBasic(t *testing.T) { + var transferAuthz types.TransferAuthorization + + testCases := []struct { + name string + malleate func() + expPass bool + }{ + { + "success", + func() {}, + true, + }, + { + "success: empty allow list", + func() { + transferAuthz.Allocations[0].AllowList = []string{} + }, + true, + }, + { + "success: with multiple allocations", + func() { + allocation := types.Allocation{ + SourcePort: types.PortID, + SourceChannel: ibctesting.FirstChannelID, + SpendLimit: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100))), + AllowList: []string{}, + } + + transferAuthz.Allocations = append(transferAuthz.Allocations, allocation) + }, + true, + }, + { + "empty allocations", + func() { + transferAuthz = types.TransferAuthorization{Allocations: []types.Allocation{}} + }, + false, + }, + { + "nil allocations", + func() { + transferAuthz = types.TransferAuthorization{} + }, + false, + }, + { + "nil spend limit coins", + func() { + transferAuthz.Allocations[0].SpendLimit = nil + }, + false, + }, + { + "invalid spend limit coins", + func() { + transferAuthz.Allocations[0].SpendLimit = sdk.Coins{sdk.Coin{Denom: ""}} + }, + false, + }, + { + "duplicate entry in allow list", + func() { + transferAuthz.Allocations[0].AllowList = []string{ibctesting.TestAccAddress, ibctesting.TestAccAddress} + }, + false, + }, + { + "invalid port identifier", + func() { + transferAuthz.Allocations[0].SourcePort = "" + }, + false, + }, + { + "invalid channel identifier", + func() { + transferAuthz.Allocations[0].SourceChannel = "" + }, + false, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + transferAuthz = types.TransferAuthorization{ + Allocations: []types.Allocation{ + { + SourcePort: mock.PortID, + SourceChannel: ibctesting.FirstChannelID, + SpendLimit: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100))), + AllowList: []string{ibctesting.TestAccAddress}, + }, + }, + } + + tc.malleate() + + err := transferAuthz.ValidateBasic() + + if tc.expPass { + require.NoError(t, err) + } else { + require.Error(t, err) + } + }) + } +} From dd1aa5aa227cfe6a98a89867af1f3d5bc1eadccd Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Mon, 16 Jan 2023 11:42:52 +0100 Subject: [PATCH 10/18] chore: refactor transfer authz tests to use table tests (#2998) * moving authz protos to transfer.v1 * running make format * rename allow list and allocation protobuf types * use fully qualified interface name in authz.proto * adding validate basic tests * if allow list is empty, permit any receiver * test formatting * test setup for transfer authz accept * refactoring unit tests * apply suggestions from review --- .../types/transfer_authorization_test.go | 254 ++++++++++-------- .../types/{ack_test.go => types_test.go} | 11 + 2 files changed, 153 insertions(+), 112 deletions(-) rename modules/apps/transfer/types/{ack_test.go => types_test.go} (59%) diff --git a/modules/apps/transfer/types/transfer_authorization_test.go b/modules/apps/transfer/types/transfer_authorization_test.go index d1c6cc7fb12..0ac266e6a38 100644 --- a/modules/apps/transfer/types/transfer_authorization_test.go +++ b/modules/apps/transfer/types/transfer_authorization_test.go @@ -1,132 +1,162 @@ package types_test import ( - "testing" - - "github.com/stretchr/testify/require" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - - "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/authz" + "github.com/cosmos/ibc-go/v6/modules/apps/transfer/types" - clienttypes "github.com/cosmos/ibc-go/v6/modules/core/02-client/types" ibctesting "github.com/cosmos/ibc-go/v6/testing" "github.com/cosmos/ibc-go/v6/testing/mock" ) -var ( - sourcePort = "port" - sourceChannel = "channel-100" - sourcePort2 = "port2" - sourceChannel2 = "channel-101" - coins1000 = sdk.Coins{sdk.NewCoin("stake", sdk.NewInt(1000))} - coins500 = sdk.Coins{sdk.NewCoin("stake", sdk.NewInt(500))} - coin1000 = sdk.NewCoin("stake", sdk.NewInt(1000)) - coin500 = sdk.NewCoin("stake", sdk.NewInt(500)) - fromAddr = sdk.AccAddress("_____from _____") - toAddr = sdk.AccAddress("_______to________") - timeoutHeight = clienttypes.NewHeight(0, 10) -) +func (suite *TypesTestSuite) TestTransferAuthorizationAccept() { + var ( + msgTransfer types.MsgTransfer + transferAuthz types.TransferAuthorization + ) -func TestTransferAuthorization(t *testing.T) { - app := simapp.Setup(t, false) - ctx := app.BaseApp.NewContext(false, tmproto.Header{}) - allocation := types.Allocation{ - SourcePort: sourcePort, - SourceChannel: sourceChannel, - SpendLimit: coins1000, - AllowList: []string{toAddr.String()}, - } - authorization := types.NewTransferAuthorization(allocation) - - t.Log("verify authorization returns valid method name") - require.Equal(t, authorization.MsgTypeURL(), "/ibc.applications.transfer.v1.MsgTransfer") - require.NoError(t, authorization.ValidateBasic()) - transfer := types.NewMsgTransfer(sourcePort, sourceChannel, coin1000, fromAddr.String(), toAddr.String(), timeoutHeight, 0, "") - require.NoError(t, authorization.ValidateBasic()) - - t.Log("verify updated authorization returns nil") - resp, err := authorization.Accept(ctx, transfer) - require.NoError(t, err) - require.True(t, resp.Delete) - require.Nil(t, resp.Updated) - - t.Log("verify updated authorization returns remaining spent limit") - authorization = types.NewTransferAuthorization(allocation) - require.Equal(t, authorization.MsgTypeURL(), "/ibc.applications.transfer.v1.MsgTransfer") - require.NoError(t, authorization.ValidateBasic()) - transfer = types.NewMsgTransfer(sourcePort, sourceChannel, coin500, fromAddr.String(), toAddr.String(), timeoutHeight, 0, "") - require.NoError(t, authorization.ValidateBasic()) - resp, err = authorization.Accept(ctx, transfer) - require.NoError(t, err) - require.False(t, resp.Delete) - require.NotNil(t, resp.Updated) - - allocation = types.Allocation{ - SourcePort: sourcePort, - SourceChannel: sourceChannel, - SpendLimit: coins500, - AllowList: []string{toAddr.String()}, - } - sendAuth := types.NewTransferAuthorization(allocation) - require.Equal(t, sendAuth.String(), resp.Updated.String()) - - t.Log("expect updated authorization nil after spending remaining amount") - resp, err = resp.Updated.Accept(ctx, transfer) - require.NoError(t, err) - require.True(t, resp.Delete) - require.Nil(t, resp.Updated) - - t.Log("expect error when spend limit for specific port and channel is not set") - allocation = types.Allocation{ - SourcePort: sourcePort, - SourceChannel: sourceChannel, - SpendLimit: coins1000, - AllowList: []string{toAddr.String()}, - } - authorization = types.NewTransferAuthorization(allocation) - transfer = types.NewMsgTransfer(sourcePort2, sourceChannel2, coin500, fromAddr.String(), toAddr.String(), timeoutHeight, 0, "") - _, err = authorization.Accept(ctx, transfer) - require.Error(t, err) + testCases := []struct { + name string + malleate func() + assertResult func(res authz.AcceptResponse, err error) + }{ + { + "success", + func() {}, + func(res authz.AcceptResponse, err error) { + suite.Require().NoError(err) + + suite.Require().True(res.Accept) + suite.Require().True(res.Delete) + suite.Require().Nil(res.Updated) + }, + }, + { + "success: with spend limit updated", + func() { + msgTransfer.Token = sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(50)) + }, + func(res authz.AcceptResponse, err error) { + suite.Require().NoError(err) + + suite.Require().True(res.Accept) + suite.Require().False(res.Delete) + + updatedAuthz, ok := res.Updated.(*types.TransferAuthorization) + suite.Require().True(ok) + + isEqual := updatedAuthz.Allocations[0].SpendLimit.IsEqual(sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(50)))) + suite.Require().True(isEqual) + }, + }, + { + "success: with empty allow list", + func() { + transferAuthz.Allocations[0].AllowList = []string{} + }, + func(res authz.AcceptResponse, err error) { + suite.Require().NoError(err) + + suite.Require().True(res.Accept) + suite.Require().True(res.Delete) + suite.Require().Nil(res.Updated) + }, + }, + { + "success: with multiple allocations", + func() { + alloc := types.Allocation{ + SourcePort: ibctesting.MockPort, + SourceChannel: "channel-9", + SpendLimit: ibctesting.TestCoins, + } + + transferAuthz.Allocations = append(transferAuthz.Allocations, alloc) + }, + func(res authz.AcceptResponse, err error) { + suite.Require().NoError(err) + + suite.Require().True(res.Accept) + suite.Require().False(res.Delete) - t.Log("expect removing only 1 allocation if spend limit is finalized for the port") + updatedAuthz, ok := res.Updated.(*types.TransferAuthorization) + suite.Require().True(ok) - allocations := []types.Allocation{ + // assert spent spendlimit is removed from the list + suite.Require().Len(updatedAuthz.Allocations, 1) + }, + }, + { + "no spend limit set for MsgTransfer port/channel", + func() { + msgTransfer.SourcePort = ibctesting.MockPort + msgTransfer.SourceChannel = "channel-9" + }, + func(res authz.AcceptResponse, err error) { + suite.Require().Error(err) + }, + }, { - SourcePort: sourcePort, - SourceChannel: sourceChannel, - SpendLimit: coins1000, - AllowList: []string{toAddr.String()}, + "requested transfer amount is more than the spend limit", + func() { + msgTransfer.Token = sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1000)) + }, + func(res authz.AcceptResponse, err error) { + suite.Require().Error(err) + }, }, { - SourcePort: sourcePort2, - SourceChannel: sourceChannel2, - SpendLimit: coins1000, - AllowList: []string{toAddr.String()}, + "receiver address not permitted via allow list", + func() { + msgTransfer.Receiver = suite.chainB.SenderAccount.GetAddress().String() + }, + func(res authz.AcceptResponse, err error) { + suite.Require().Error(err) + }, }, } - authorization = types.NewTransferAuthorization(allocations...) - transfer = types.NewMsgTransfer(sourcePort, sourceChannel, coin1000, fromAddr.String(), toAddr.String(), timeoutHeight, 0, "") - resp, err = authorization.Accept(ctx, transfer) - require.NoError(t, err) - require.NotNil(t, resp.Updated) - require.Equal(t, resp.Updated, types.NewTransferAuthorization(allocations[1])) - require.False(t, resp.Delete) - - t.Log("expect error when transferring to not allowed address") - allocation = types.Allocation{ - SourcePort: sourcePort, - SourceChannel: sourceChannel, - SpendLimit: coins1000, - AllowList: []string{fromAddr.String()}, + + for _, tc := range testCases { + suite.Run(tc.name, func() { + suite.SetupTest() + + path := NewTransferPath(suite.chainA, suite.chainB) + suite.coordinator.Setup(path) + + transferAuthz = types.TransferAuthorization{ + Allocations: []types.Allocation{ + { + SourcePort: path.EndpointA.ChannelConfig.PortID, + SourceChannel: path.EndpointA.ChannelID, + SpendLimit: ibctesting.TestCoins, + AllowList: []string{ibctesting.TestAccAddress}, + }, + }, + } + + msgTransfer = types.MsgTransfer{ + SourcePort: path.EndpointA.ChannelConfig.PortID, + SourceChannel: path.EndpointA.ChannelID, + Token: ibctesting.TestCoin, + Sender: suite.chainA.SenderAccount.GetAddress().String(), + Receiver: ibctesting.TestAccAddress, + TimeoutHeight: suite.chainB.GetTimeoutHeight(), + } + + tc.malleate() + + res, err := transferAuthz.Accept(suite.chainA.GetContext(), &msgTransfer) + tc.assertResult(res, err) + }) } - authorization = types.NewTransferAuthorization(allocation) - transfer = types.NewMsgTransfer(sourcePort, sourceChannel, coin500, fromAddr.String(), toAddr.String(), timeoutHeight, 0, "") - _, err = authorization.Accept(ctx, transfer) - require.Error(t, err) } -func TestTransferAuthorizationValidateBasic(t *testing.T) { +func (suite *TypesTestSuite) TestTransferAuthorizationMsgTypeURL() { + var transferAuthz types.TransferAuthorization + suite.Require().Equal(sdk.MsgTypeURL(&types.MsgTransfer{}), transferAuthz.MsgTypeURL(), "invalid type url for transfer authorization") +} + +func (suite *TypesTestSuite) TestTransferAuthorizationValidateBasic() { var transferAuthz types.TransferAuthorization testCases := []struct { @@ -212,7 +242,7 @@ func TestTransferAuthorizationValidateBasic(t *testing.T) { } for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { + suite.Run(tc.name, func() { transferAuthz = types.TransferAuthorization{ Allocations: []types.Allocation{ { @@ -229,9 +259,9 @@ func TestTransferAuthorizationValidateBasic(t *testing.T) { err := transferAuthz.ValidateBasic() if tc.expPass { - require.NoError(t, err) + suite.Require().NoError(err) } else { - require.Error(t, err) + suite.Require().Error(err) } }) } diff --git a/modules/apps/transfer/types/ack_test.go b/modules/apps/transfer/types/types_test.go similarity index 59% rename from modules/apps/transfer/types/ack_test.go rename to modules/apps/transfer/types/types_test.go index 0b299d434d6..108304e5927 100644 --- a/modules/apps/transfer/types/ack_test.go +++ b/modules/apps/transfer/types/types_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/suite" + "github.com/cosmos/ibc-go/v6/modules/apps/transfer/types" ibctesting "github.com/cosmos/ibc-go/v6/testing" ) @@ -24,6 +25,16 @@ func (suite *TypesTestSuite) SetupTest() { suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(2)) } +func NewTransferPath(chainA, chainB *ibctesting.TestChain) *ibctesting.Path { + path := ibctesting.NewPath(chainA, chainB) + path.EndpointA.ChannelConfig.PortID = types.PortID + path.EndpointB.ChannelConfig.PortID = types.PortID + path.EndpointA.ChannelConfig.Version = types.Version + path.EndpointB.ChannelConfig.Version = types.Version + + return path +} + func TestTypesTestSuite(t *testing.T) { suite.Run(t, new(TypesTestSuite)) } From 05ab435345add3dee5d8b1df6d06c0689ebaac16 Mon Sep 17 00:00:00 2001 From: Cian Hatton Date: Mon, 16 Jan 2023 11:20:19 +0000 Subject: [PATCH 11/18] Add MsgRevoke to ICS20 Authz test (#2997) --- e2e/tests/transfer/authz_test.go | 35 ++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/e2e/tests/transfer/authz_test.go b/e2e/tests/transfer/authz_test.go index 4da10d7d523..906a77ec295 100644 --- a/e2e/tests/transfer/authz_test.go +++ b/e2e/tests/transfer/authz_test.go @@ -140,6 +140,41 @@ func (suite *AuthzTransferTestSuite) TestAuthz_MsgTransfer_Succeeds() { t.Run("granter grant was reinitialized", verifyGrantFn(testvalues.StartingTokenAmount)) + t.Run("revoke access", func(t *testing.T) { + msgRevoke := authz.MsgRevoke{ + Granter: granterAddress, + Grantee: granteeAddress, + MsgTypeUrl: transfertypes.TransferAuthorization{}.MsgTypeURL(), + } + + resp, err := suite.BroadcastMessages(context.TODO(), chainA, granterWallet, &msgRevoke) + suite.AssertValidTxResponse(resp) + suite.Require().NoError(err) + }) + + t.Run("exec unauthorized MsgTransfer", func(t *testing.T) { + transferMsg := transfertypes.MsgTransfer{ + SourcePort: channelA.PortID, + SourceChannel: channelA.ChannelID, + Token: testvalues.DefaultTransferAmount(chainADenom), + Sender: granterAddress, + Receiver: receiverWalletAddress, + TimeoutHeight: suite.GetTimeoutHeight(ctx, chainB), + } + + transferAny, err := codectypes.NewAnyWithValue(&transferMsg) + suite.Require().NoError(err) + + msgExec := &authz.MsgExec{ + Grantee: granteeAddress, + Msgs: []*codectypes.Any{transferAny}, + } + + resp, err := suite.BroadcastMessages(context.TODO(), chainA, granteeWallet, msgExec) + suite.Require().NotEqual(0, resp.Code) + suite.Require().Contains(resp.RawLog, authz.ErrNoAuthorizationFound.Error()) + suite.Require().NoError(err) + }) } // extractTransferAuthorizationFromGrantAuthorization extracts a TransferAuthorization from the given From b4bd0a79435a5da164d1fd1a6c56a54887d6683b Mon Sep 17 00:00:00 2001 From: Cian Hatton Date: Mon, 16 Jan 2023 12:10:30 +0000 Subject: [PATCH 12/18] chore: TransferAuthorization ValidateBasic now returns an error when there is a duplicate channel id (#3013) --- .../transfer/types/transfer_authorization.go | 9 +++++++++ .../types/transfer_authorization_test.go | 16 +++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/modules/apps/transfer/types/transfer_authorization.go b/modules/apps/transfer/types/transfer_authorization.go index 8b0a9fc56cf..244cc287c51 100644 --- a/modules/apps/transfer/types/transfer_authorization.go +++ b/modules/apps/transfer/types/transfer_authorization.go @@ -5,6 +5,7 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/authz" + channeltypes "github.com/cosmos/ibc-go/v6/modules/core/04-channel/types" host "github.com/cosmos/ibc-go/v6/modules/core/24-host" "golang.org/x/exp/slices" @@ -74,7 +75,15 @@ func (a TransferAuthorization) ValidateBasic() error { return sdkerrors.Wrap(ErrInvalidAuthorization, "allocations cannot be empty") } + foundChannels := make(map[string]bool, 0) + for _, allocation := range a.Allocations { + if _, found := foundChannels[allocation.SourceChannel]; found { + return sdkerrors.Wrapf(channeltypes.ErrInvalidChannel, "duplicate source channel ID: %s", allocation.SourceChannel) + } + + foundChannels[allocation.SourceChannel] = true + if allocation.SpendLimit == nil { return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, "spend limit cannot be nil") } diff --git a/modules/apps/transfer/types/transfer_authorization_test.go b/modules/apps/transfer/types/transfer_authorization_test.go index 0ac266e6a38..2e2f51bd81a 100644 --- a/modules/apps/transfer/types/transfer_authorization_test.go +++ b/modules/apps/transfer/types/transfer_authorization_test.go @@ -181,7 +181,7 @@ func (suite *TypesTestSuite) TestTransferAuthorizationValidateBasic() { func() { allocation := types.Allocation{ SourcePort: types.PortID, - SourceChannel: ibctesting.FirstChannelID, + SourceChannel: "channel-1", SpendLimit: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100))), AllowList: []string{}, } @@ -239,6 +239,20 @@ func (suite *TypesTestSuite) TestTransferAuthorizationValidateBasic() { }, false, }, + { + name: "duplicate channel ID", + malleate: func() { + allocation := types.Allocation{ + SourcePort: mock.PortID, + SourceChannel: transferAuthz.Allocations[0].SourceChannel, + SpendLimit: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100))), + AllowList: []string{ibctesting.TestAccAddress}, + } + + transferAuthz.Allocations = append(transferAuthz.Allocations, allocation) + }, + expPass: false, + }, } for _, tc := range testCases { From ee9db57b340a9a9a13831033731e6cad4850b579 Mon Sep 17 00:00:00 2001 From: Cian Hatton Date: Wed, 18 Jan 2023 09:17:01 +0000 Subject: [PATCH 13/18] E2E Test for spend limit and invalid addresses (#3000) --- e2e/tests/transfer/authz_test.go | 138 +++++++++++++++++++++++++++++++ e2e/testvalues/values.go | 2 +- 2 files changed, 139 insertions(+), 1 deletion(-) diff --git a/e2e/tests/transfer/authz_test.go b/e2e/tests/transfer/authz_test.go index 906a77ec295..311758c11b2 100644 --- a/e2e/tests/transfer/authz_test.go +++ b/e2e/tests/transfer/authz_test.go @@ -6,6 +6,7 @@ import ( codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/authz" test "github.com/strangelove-ventures/ibctest/v6/testutil" "github.com/stretchr/testify/suite" @@ -177,6 +178,143 @@ func (suite *AuthzTransferTestSuite) TestAuthz_MsgTransfer_Succeeds() { }) } +func (suite *AuthzTransferTestSuite) TestAuthz_InvalidTransferAuthorizations() { + t := suite.T() + ctx := context.TODO() + + relayer, channelA := suite.SetupChainsRelayerAndChannel(ctx, transferChannelOptions()) + chainA, chainB := suite.GetChains() + + chainADenom := chainA.Config().Denom + + granterWallet := suite.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) + granterAddress := granterWallet.Bech32Address(chainA.Config().Bech32Prefix) + + granteeWallet := suite.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) + granteeAddress := granteeWallet.Bech32Address(chainA.Config().Bech32Prefix) + + receiverWallet := suite.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount) + receiverWalletAddress := receiverWallet.Bech32Address(chainB.Config().Bech32Prefix) + + t.Run("start relayer", func(t *testing.T) { + suite.StartRelayer(relayer) + }) + + const spendLimit = 1000 + + t.Run("broadcast MsgGrant", func(t *testing.T) { + transferAuth := transfertypes.TransferAuthorization{ + Allocations: []transfertypes.Allocation{ + { + SourcePort: channelA.PortID, + SourceChannel: channelA.ChannelID, + SpendLimit: sdk.NewCoins(sdk.NewCoin(chainADenom, sdk.NewInt(spendLimit))), + AllowList: []string{receiverWalletAddress}, + }, + }, + } + + authAny, err := codectypes.NewAnyWithValue(&transferAuth) + suite.Require().NoError(err) + + msgGrant := &authz.MsgGrant{ + Granter: granterAddress, + Grantee: granteeAddress, + Grant: authz.Grant{ + Authorization: authAny, + // no expiration + Expiration: nil, + }, + } + + resp, err := suite.BroadcastMessages(context.TODO(), chainA, granterWallet, msgGrant) + suite.AssertValidTxResponse(resp) + suite.Require().NoError(err) + }) + + t.Run("exceed spend limit", func(t *testing.T) { + const invalidSpendAmount = spendLimit + 1 + + t.Run("broadcast MsgExec for ibc MsgTransfer", func(t *testing.T) { + transferMsg := transfertypes.MsgTransfer{ + SourcePort: channelA.PortID, + SourceChannel: channelA.ChannelID, + Token: sdk.Coin{Denom: chainADenom, Amount: sdk.NewInt(invalidSpendAmount)}, + Sender: granterAddress, + Receiver: receiverWalletAddress, + TimeoutHeight: suite.GetTimeoutHeight(ctx, chainB), + } + + transferAny, err := codectypes.NewAnyWithValue(&transferMsg) + suite.Require().NoError(err) + + msgExec := &authz.MsgExec{ + Grantee: granteeAddress, + Msgs: []*codectypes.Any{transferAny}, + } + + resp, err := suite.BroadcastMessages(context.TODO(), chainA, granteeWallet, msgExec) + suite.Require().NotEqual(0, resp.Code) + suite.Require().Contains(resp.RawLog, sdkerrors.ErrInsufficientFunds.Error()) + suite.Require().NoError(err) + }) + + t.Run("verify granter wallet amount", func(t *testing.T) { + actualBalance, err := suite.GetChainANativeBalance(ctx, granterWallet) + suite.Require().NoError(err) + suite.Require().Equal(testvalues.StartingTokenAmount, actualBalance) + }) + + t.Run("verify receiver wallet amount", func(t *testing.T) { + chainBIBCToken := testsuite.GetIBCToken(chainADenom, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID) + actualBalance, err := chainB.GetBalance(ctx, receiverWalletAddress, chainBIBCToken.IBCDenom()) + suite.Require().NoError(err) + suite.Require().Equal(int64(0), actualBalance) + }) + + t.Run("granter grant spend limit unchanged", func(t *testing.T) { + grantAuths, err := suite.QueryGranterGrants(ctx, chainA, granterAddress) + + suite.Require().NoError(err) + suite.Require().Len(grantAuths, 1) + grantAuthorization := grantAuths[0] + + transferAuth := suite.extractTransferAuthorizationFromGrantAuthorization(grantAuthorization) + expectedSpendLimit := sdk.NewCoins(sdk.NewCoin(chainADenom, sdk.NewInt(spendLimit))) + suite.Require().Equal(expectedSpendLimit, transferAuth.Allocations[0].SpendLimit) + }) + }) + + t.Run("send funds to invalid address", func(t *testing.T) { + invalidWallet := suite.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount) + invalidWalletAddress := invalidWallet.Bech32Address(chainB.Config().Bech32Prefix) + + t.Run("broadcast MsgExec for ibc MsgTransfer", func(t *testing.T) { + transferMsg := transfertypes.MsgTransfer{ + SourcePort: channelA.PortID, + SourceChannel: channelA.ChannelID, + Token: sdk.Coin{Denom: chainADenom, Amount: sdk.NewInt(spendLimit)}, + Sender: granterAddress, + Receiver: invalidWalletAddress, + TimeoutHeight: suite.GetTimeoutHeight(ctx, chainB), + } + + transferAny, err := codectypes.NewAnyWithValue(&transferMsg) + suite.Require().NoError(err) + + msgExec := &authz.MsgExec{ + Grantee: granteeAddress, + Msgs: []*codectypes.Any{transferAny}, + } + + resp, err := suite.BroadcastMessages(context.TODO(), chainA, granteeWallet, msgExec) + suite.Require().NotEqual(0, resp.Code) + suite.Require().Contains(resp.RawLog, sdkerrors.ErrInvalidAddress.Error()) + suite.Require().NoError(err) + }) + }) +} + // extractTransferAuthorizationFromGrantAuthorization extracts a TransferAuthorization from the given // GrantAuthorization. func (suite *AuthzTransferTestSuite) extractTransferAuthorizationFromGrantAuthorization(grantAuth *authz.GrantAuthorization) *transfertypes.TransferAuthorization { diff --git a/e2e/testvalues/values.go b/e2e/testvalues/values.go index 3e95f5cddf8..eedf831cc95 100644 --- a/e2e/testvalues/values.go +++ b/e2e/testvalues/values.go @@ -41,5 +41,5 @@ func TendermintClientID(id int) string { } func SolomachineClientID(id int) string { - return fmt.Sprint("06-solomachine-%d", id) + return fmt.Sprintf("06-solomachine-%d", id) } From b7e229ef808af973e2f87291961a9c3785cdf795 Mon Sep 17 00:00:00 2001 From: crodriguezvega Date: Sun, 29 Jan 2023 11:34:19 +0100 Subject: [PATCH 14/18] fix v7 import paths --- e2e/tests/transfer/authz_test.go | 2 +- go.mod | 2 +- modules/apps/transfer/types/authz.pb.go | 58 +++++++++---------- .../transfer/types/transfer_authorization.go | 4 +- .../types/transfer_authorization_test.go | 6 +- .../ibc/applications/transfer/v1/authz.proto | 2 +- 6 files changed, 37 insertions(+), 37 deletions(-) diff --git a/e2e/tests/transfer/authz_test.go b/e2e/tests/transfer/authz_test.go index 311758c11b2..df7ae7ad62d 100644 --- a/e2e/tests/transfer/authz_test.go +++ b/e2e/tests/transfer/authz_test.go @@ -13,7 +13,7 @@ import ( "github.com/cosmos/ibc-go/e2e/testsuite" "github.com/cosmos/ibc-go/e2e/testvalues" - transfertypes "github.com/cosmos/ibc-go/v6/modules/apps/transfer/types" + transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" ) func TestAuthzTransferTestSuite(t *testing.T) { diff --git a/go.mod b/go.mod index 043236f2a47..7fb262f0c5f 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/stretchr/testify v1.8.1 github.com/tendermint/tendermint v0.37.0-rc2 github.com/tendermint/tm-db v0.6.7 - golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e + golang.org/x/exp v0.0.0-20221019170559-20944726eadf google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef google.golang.org/grpc v1.52.3 google.golang.org/protobuf v1.28.1 diff --git a/modules/apps/transfer/types/authz.pb.go b/modules/apps/transfer/types/authz.pb.go index 1e81b9968f4..95f24eca332 100644 --- a/modules/apps/transfer/types/authz.pb.go +++ b/modules/apps/transfer/types/authz.pb.go @@ -8,8 +8,8 @@ import ( _ "github.com/cosmos/cosmos-proto" github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" types "github.com/cosmos/cosmos-sdk/types" - _ "github.com/gogo/protobuf/gogoproto" - proto "github.com/gogo/protobuf/proto" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" io "io" math "math" math_bits "math/bits" @@ -156,35 +156,35 @@ func init() { } var fileDescriptor_b1a28b55d17325aa = []byte{ - // 436 bytes of a gzipped FileDescriptorProto + // 435 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x52, 0x4d, 0x6e, 0xd3, 0x40, 0x14, 0x8e, 0x9b, 0x0a, 0x29, 0x13, 0xc1, 0xc2, 0xa2, 0xc8, 0xa9, 0xc0, 0x89, 0xbc, 0x40, 0xde, - 0x64, 0x86, 0x80, 0x44, 0xa5, 0xae, 0x68, 0xba, 0xed, 0xa2, 0x58, 0xac, 0xd8, 0x44, 0xe3, 0xc9, - 0x60, 0x8f, 0x18, 0xfb, 0x59, 0x9e, 0xb1, 0x51, 0x7b, 0x0a, 0x90, 0x38, 0x05, 0x6b, 0x0e, 0x51, - 0xb1, 0xea, 0x92, 0x55, 0x40, 0xc9, 0x0d, 0x7a, 0x02, 0xe4, 0x99, 0x29, 0xb8, 0x42, 0xea, 0xca, - 0x7e, 0x3f, 0xdf, 0x7b, 0xdf, 0xfb, 0xe6, 0x43, 0xb1, 0x48, 0x19, 0xa1, 0x55, 0x25, 0x05, 0xa3, - 0x5a, 0x40, 0xa9, 0x88, 0xae, 0x69, 0xa9, 0x3e, 0xf0, 0x9a, 0xb4, 0x0b, 0x42, 0x1b, 0x9d, 0x5f, - 0xe2, 0xaa, 0x06, 0x0d, 0xfe, 0x53, 0x91, 0x32, 0xdc, 0xef, 0xc4, 0xb7, 0x9d, 0xb8, 0x5d, 0x1c, - 0x4e, 0x18, 0xa8, 0x02, 0xd4, 0xca, 0xf4, 0x12, 0x1b, 0x58, 0xe0, 0xe1, 0xe3, 0x0c, 0x32, 0xb0, - 0xf9, 0xee, 0xcf, 0x65, 0x43, 0xdb, 0x43, 0x52, 0xaa, 0x38, 0x69, 0x17, 0x29, 0xd7, 0x74, 0x41, - 0x18, 0x88, 0xd2, 0xd6, 0xa3, 0xaf, 0x7b, 0x08, 0x9d, 0x48, 0x09, 0x76, 0x99, 0x7f, 0x84, 0xc6, - 0x0a, 0x9a, 0x9a, 0xf1, 0x55, 0x05, 0xb5, 0x0e, 0xbc, 0x99, 0x17, 0x8f, 0x96, 0x4f, 0x6e, 0x36, - 0x53, 0xff, 0x82, 0x16, 0xf2, 0x38, 0xea, 0x15, 0xa3, 0x04, 0xd9, 0xe8, 0x1c, 0x6a, 0xed, 0xbf, - 0x41, 0x8f, 0x5c, 0x8d, 0xe5, 0xb4, 0x2c, 0xb9, 0x0c, 0xf6, 0x0c, 0x76, 0x72, 0xb3, 0x99, 0x1e, - 0xdc, 0xc1, 0xba, 0x7a, 0x94, 0x3c, 0xb4, 0x89, 0x53, 0x1b, 0xfb, 0x12, 0x8d, 0x55, 0xc5, 0xcb, - 0xf5, 0x4a, 0x8a, 0x42, 0xe8, 0x60, 0x38, 0x1b, 0xc6, 0xe3, 0x97, 0x13, 0xec, 0x6e, 0xec, 0xf8, - 0x63, 0xc7, 0x1f, 0x9f, 0x82, 0x28, 0x97, 0x2f, 0xae, 0x36, 0xd3, 0xc1, 0xb7, 0x5f, 0xd3, 0x38, - 0x13, 0x3a, 0x6f, 0x52, 0xcc, 0xa0, 0x70, 0x82, 0xb8, 0xcf, 0x5c, 0xad, 0x3f, 0x12, 0x7d, 0x51, - 0x71, 0x65, 0x00, 0x2a, 0x41, 0x66, 0xfe, 0x59, 0x37, 0xde, 0x7f, 0x86, 0x10, 0x95, 0x12, 0x3e, - 0xad, 0xa4, 0x50, 0x3a, 0xd8, 0x9f, 0x0d, 0xe3, 0x51, 0x32, 0x32, 0x99, 0x33, 0xa1, 0x74, 0xf4, - 0xc5, 0x43, 0x07, 0xef, 0x9c, 0xee, 0x27, 0x8d, 0xce, 0xa1, 0x16, 0x97, 0x56, 0xa1, 0x73, 0x34, - 0xa6, 0x7f, 0xf5, 0x52, 0x81, 0x67, 0x68, 0xc6, 0xf8, 0xbe, 0x57, 0xc3, 0xff, 0x04, 0x5e, 0xee, - 0x77, 0xac, 0x93, 0xfe, 0x88, 0xe3, 0xe7, 0x3f, 0xbe, 0xcf, 0x23, 0x77, 0xa6, 0x75, 0xc2, 0xed, - 0x9d, 0x77, 0x36, 0x2f, 0xdf, 0x5e, 0x6d, 0x43, 0xef, 0x7a, 0x1b, 0x7a, 0xbf, 0xb7, 0xa1, 0xf7, - 0x79, 0x17, 0x0e, 0xae, 0x77, 0xe1, 0xe0, 0xe7, 0x2e, 0x1c, 0xbc, 0x3f, 0xfa, 0x5f, 0x02, 0x91, - 0xb2, 0x79, 0x06, 0xa4, 0x7d, 0x4d, 0x0a, 0x58, 0x37, 0x92, 0xab, 0xce, 0x7d, 0x3d, 0xd7, 0x19, - 0x5d, 0xd2, 0x07, 0xc6, 0x04, 0xaf, 0xfe, 0x04, 0x00, 0x00, 0xff, 0xff, 0x7e, 0xff, 0x95, 0x1c, - 0x9f, 0x02, 0x00, 0x00, + 0x64, 0x86, 0xc0, 0x22, 0x52, 0x57, 0x34, 0xdd, 0x76, 0x51, 0x2c, 0x56, 0x6c, 0xa2, 0xf1, 0x64, + 0xb0, 0x47, 0x8c, 0xfd, 0x2c, 0xcf, 0xd8, 0xa8, 0x3d, 0x05, 0x48, 0x9c, 0x82, 0x35, 0x87, 0xa8, + 0x58, 0x75, 0xc9, 0x2a, 0xa0, 0xe4, 0x06, 0x3d, 0x01, 0xf2, 0xcc, 0x14, 0x5c, 0x21, 0xb1, 0xb2, + 0xdf, 0xcf, 0xf7, 0xde, 0xf7, 0xbe, 0xf9, 0x50, 0x2c, 0x52, 0x46, 0x68, 0x55, 0x49, 0xc1, 0xa8, + 0x16, 0x50, 0x2a, 0xa2, 0x6b, 0x5a, 0xaa, 0xf7, 0xbc, 0x26, 0xed, 0x82, 0xd0, 0x46, 0xe7, 0x57, + 0xb8, 0xaa, 0x41, 0x83, 0xff, 0x54, 0xa4, 0x0c, 0xf7, 0x3b, 0xf1, 0x5d, 0x27, 0x6e, 0x17, 0xc7, + 0x13, 0x06, 0xaa, 0x00, 0xb5, 0x36, 0xbd, 0xc4, 0x06, 0x16, 0x78, 0xfc, 0x38, 0x83, 0x0c, 0x6c, + 0xbe, 0xfb, 0x73, 0xd9, 0xd0, 0xf6, 0x90, 0x94, 0x2a, 0x4e, 0xda, 0x45, 0xca, 0x35, 0x5d, 0x10, + 0x06, 0xa2, 0xb4, 0xf5, 0xe8, 0xcb, 0x01, 0x42, 0xa7, 0x52, 0x82, 0x5d, 0xe6, 0x2f, 0xd1, 0x58, + 0x41, 0x53, 0x33, 0xbe, 0xae, 0xa0, 0xd6, 0x81, 0x37, 0xf3, 0xe2, 0xd1, 0xea, 0xc9, 0xed, 0x76, + 0xea, 0x5f, 0xd2, 0x42, 0x9e, 0x44, 0xbd, 0x62, 0x94, 0x20, 0x1b, 0x5d, 0x40, 0xad, 0xfd, 0xd7, + 0xe8, 0x91, 0xab, 0xb1, 0x9c, 0x96, 0x25, 0x97, 0xc1, 0x81, 0xc1, 0x4e, 0x6e, 0xb7, 0xd3, 0xa3, + 0x7b, 0x58, 0x57, 0x8f, 0x92, 0x87, 0x36, 0x71, 0x66, 0x63, 0x5f, 0xa2, 0xb1, 0xaa, 0x78, 0xb9, + 0x59, 0x4b, 0x51, 0x08, 0x1d, 0x0c, 0x67, 0xc3, 0x78, 0xfc, 0x72, 0x82, 0xdd, 0x8d, 0x1d, 0x7f, + 0xec, 0xf8, 0xe3, 0x33, 0x10, 0xe5, 0xea, 0xc5, 0xf5, 0x76, 0x3a, 0xf8, 0xfa, 0x73, 0x1a, 0x67, + 0x42, 0xe7, 0x4d, 0x8a, 0x19, 0x14, 0x4e, 0x10, 0xf7, 0x99, 0xab, 0xcd, 0x07, 0xa2, 0x2f, 0x2b, + 0xae, 0x0c, 0x40, 0x25, 0xc8, 0xcc, 0x3f, 0xef, 0xc6, 0xfb, 0xcf, 0x10, 0xa2, 0x52, 0xc2, 0xc7, + 0xb5, 0x14, 0x4a, 0x07, 0x87, 0xb3, 0x61, 0x3c, 0x4a, 0x46, 0x26, 0x73, 0x2e, 0x94, 0x8e, 0x3e, + 0x7b, 0xe8, 0xe8, 0xad, 0xd3, 0xfd, 0xb4, 0xd1, 0x39, 0xd4, 0xe2, 0xca, 0x2a, 0x74, 0x81, 0xc6, + 0xf4, 0x8f, 0x5e, 0x2a, 0xf0, 0x0c, 0xcd, 0x18, 0xff, 0xef, 0xd5, 0xf0, 0x5f, 0x81, 0x57, 0x87, + 0x1d, 0xeb, 0xa4, 0x3f, 0xe2, 0xe4, 0xf9, 0xf7, 0x6f, 0xf3, 0xc8, 0x9d, 0x69, 0x9d, 0x70, 0x77, + 0xe7, 0xbd, 0xcd, 0xab, 0x37, 0xd7, 0xbb, 0xd0, 0xbb, 0xd9, 0x85, 0xde, 0xaf, 0x5d, 0xe8, 0x7d, + 0xda, 0x87, 0x83, 0x9b, 0x7d, 0x38, 0xf8, 0xb1, 0x0f, 0x07, 0xef, 0x96, 0xff, 0x4a, 0x20, 0x52, + 0x36, 0xcf, 0x80, 0xb4, 0x4b, 0x52, 0xc0, 0xa6, 0x91, 0x5c, 0x75, 0xee, 0xeb, 0xb9, 0xce, 0xe8, + 0x92, 0x3e, 0x30, 0x26, 0x78, 0xf5, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x61, 0xe8, 0x65, 0x9c, 0x9f, + 0x02, 0x00, 0x00, } func (m *Allocation) Marshal() (dAtA []byte, err error) { diff --git a/modules/apps/transfer/types/transfer_authorization.go b/modules/apps/transfer/types/transfer_authorization.go index 244cc287c51..dfd364063c9 100644 --- a/modules/apps/transfer/types/transfer_authorization.go +++ b/modules/apps/transfer/types/transfer_authorization.go @@ -5,8 +5,8 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/authz" - channeltypes "github.com/cosmos/ibc-go/v6/modules/core/04-channel/types" - host "github.com/cosmos/ibc-go/v6/modules/core/24-host" + channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" + host "github.com/cosmos/ibc-go/v7/modules/core/24-host" "golang.org/x/exp/slices" ) diff --git a/modules/apps/transfer/types/transfer_authorization_test.go b/modules/apps/transfer/types/transfer_authorization_test.go index 2e2f51bd81a..f0f7f3ab0b9 100644 --- a/modules/apps/transfer/types/transfer_authorization_test.go +++ b/modules/apps/transfer/types/transfer_authorization_test.go @@ -4,9 +4,9 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/authz" - "github.com/cosmos/ibc-go/v6/modules/apps/transfer/types" - ibctesting "github.com/cosmos/ibc-go/v6/testing" - "github.com/cosmos/ibc-go/v6/testing/mock" + "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" + ibctesting "github.com/cosmos/ibc-go/v7/testing" + "github.com/cosmos/ibc-go/v7/testing/mock" ) func (suite *TypesTestSuite) TestTransferAuthorizationAccept() { diff --git a/proto/ibc/applications/transfer/v1/authz.proto b/proto/ibc/applications/transfer/v1/authz.proto index 53113bf5e11..8b27ac9cf7d 100644 --- a/proto/ibc/applications/transfer/v1/authz.proto +++ b/proto/ibc/applications/transfer/v1/authz.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package ibc.applications.transfer.v1; -option go_package = "github.com/cosmos/ibc-go/v6/modules/apps/transfer/types"; +option go_package = "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"; import "cosmos_proto/cosmos.proto"; import "gogoproto/gogo.proto"; From d03147e2e7796e3dcaf84100b3b3572a9e41914a Mon Sep 17 00:00:00 2001 From: crodriguezvega Date: Sun, 29 Jan 2023 11:54:16 +0100 Subject: [PATCH 15/18] fix import path --- e2e/tests/transfer/authz_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/tests/transfer/authz_test.go b/e2e/tests/transfer/authz_test.go index df7ae7ad62d..5ae5f9deb9e 100644 --- a/e2e/tests/transfer/authz_test.go +++ b/e2e/tests/transfer/authz_test.go @@ -8,7 +8,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/authz" - test "github.com/strangelove-ventures/ibctest/v6/testutil" + test "github.com/strangelove-ventures/ibctest/v7/testutil" "github.com/stretchr/testify/suite" "github.com/cosmos/ibc-go/e2e/testsuite" From 7d295c4069275bca503c7d54699170ed690be300 Mon Sep 17 00:00:00 2001 From: crodriguezvega Date: Sun, 29 Jan 2023 20:49:16 +0100 Subject: [PATCH 16/18] replace usage of Bech32Address with FormattedAddress --- e2e/tests/transfer/authz_test.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/e2e/tests/transfer/authz_test.go b/e2e/tests/transfer/authz_test.go index 5ae5f9deb9e..fef88d873fc 100644 --- a/e2e/tests/transfer/authz_test.go +++ b/e2e/tests/transfer/authz_test.go @@ -34,13 +34,13 @@ func (suite *AuthzTransferTestSuite) TestAuthz_MsgTransfer_Succeeds() { chainADenom := chainA.Config().Denom granterWallet := suite.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) - granterAddress := granterWallet.Bech32Address(chainA.Config().Bech32Prefix) + granterAddress := granterWallet.FormattedAddress() granteeWallet := suite.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) - granteeAddress := granteeWallet.Bech32Address(chainA.Config().Bech32Prefix) + granteeAddress := granteeWallet.FormattedAddress() receiverWallet := suite.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount) - receiverWalletAddress := receiverWallet.Bech32Address(chainB.Config().Bech32Prefix) + receiverWalletAddress := receiverWallet.FormattedAddress() t.Run("start relayer", func(t *testing.T) { suite.StartRelayer(relayer) @@ -188,13 +188,13 @@ func (suite *AuthzTransferTestSuite) TestAuthz_InvalidTransferAuthorizations() { chainADenom := chainA.Config().Denom granterWallet := suite.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) - granterAddress := granterWallet.Bech32Address(chainA.Config().Bech32Prefix) + granterAddress := granterWallet.FormattedAddress() granteeWallet := suite.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) - granteeAddress := granteeWallet.Bech32Address(chainA.Config().Bech32Prefix) + granteeAddress := granteeWallet.FormattedAddress() receiverWallet := suite.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount) - receiverWalletAddress := receiverWallet.Bech32Address(chainB.Config().Bech32Prefix) + receiverWalletAddress := receiverWallet.FormattedAddress() t.Run("start relayer", func(t *testing.T) { suite.StartRelayer(relayer) @@ -287,7 +287,7 @@ func (suite *AuthzTransferTestSuite) TestAuthz_InvalidTransferAuthorizations() { t.Run("send funds to invalid address", func(t *testing.T) { invalidWallet := suite.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount) - invalidWalletAddress := invalidWallet.Bech32Address(chainB.Config().Bech32Prefix) + invalidWalletAddress := invalidWallet.FormattedAddress() t.Run("broadcast MsgExec for ibc MsgTransfer", func(t *testing.T) { transferMsg := transfertypes.MsgTransfer{ From 0e9f475b6dccccc1848e29964cc58b255ffcff1a Mon Sep 17 00:00:00 2001 From: Cian Hatton Date: Wed, 1 Feb 2023 15:20:50 +0000 Subject: [PATCH 17/18] chore: replace use of exp slices package with in line deletion --- modules/apps/transfer/types/transfer_authorization.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/apps/transfer/types/transfer_authorization.go b/modules/apps/transfer/types/transfer_authorization.go index dfd364063c9..fed33b0a909 100644 --- a/modules/apps/transfer/types/transfer_authorization.go +++ b/modules/apps/transfer/types/transfer_authorization.go @@ -7,8 +7,6 @@ import ( channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" host "github.com/cosmos/ibc-go/v7/modules/core/24-host" - - "golang.org/x/exp/slices" ) const gasCostPerIteration = uint64(10) @@ -46,7 +44,7 @@ func (a TransferAuthorization) Accept(ctx sdk.Context, msg sdk.Msg) (authz.Accep } if limitLeft.IsZero() { - a.Allocations = slices.Delete(a.Allocations, index, index+1) + a.Allocations = append(a.Allocations[:index], a.Allocations[index+1:]...) if len(a.Allocations) == 0 { return authz.AcceptResponse{Accept: true, Delete: true}, nil } From 1db27a840d395525bfb1bc9fe6ea0d609297c743 Mon Sep 17 00:00:00 2001 From: Cian Hatton Date: Wed, 1 Feb 2023 16:57:22 +0000 Subject: [PATCH 18/18] chore: fixing interchaintest import --- e2e/tests/transfer/authz_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/tests/transfer/authz_test.go b/e2e/tests/transfer/authz_test.go index fef88d873fc..c70dfe0e834 100644 --- a/e2e/tests/transfer/authz_test.go +++ b/e2e/tests/transfer/authz_test.go @@ -8,7 +8,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/authz" - test "github.com/strangelove-ventures/ibctest/v7/testutil" + test "github.com/strangelove-ventures/interchaintest/v7/testutil" "github.com/stretchr/testify/suite" "github.com/cosmos/ibc-go/e2e/testsuite"