Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat(core, apps): 'PacketData' interface added and implemented #4200

Merged
merged 19 commits into from
Aug 1, 2023
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions modules/apps/27-interchain-accounts/types/packet.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
package types

import (
"strings"
"time"

errorsmod "cosmossdk.io/errors"

codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"

ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported"
)

var _ ibcexported.PacketData = (*InterchainAccountPacketData)(nil)

// MaxMemoCharLength defines the maximum length for the InterchainAccountPacketData memo field
const MaxMemoCharLength = 256

Expand Down Expand Up @@ -64,3 +69,19 @@ func (ct CosmosTx) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {

return nil
}

// GetPacketSender returns the sender address of the interchain accounts packet data.
// It is obtained from the source port ID by cutting off the ControllerPortPrefix.
// If the source port ID does not have the ControllerPortPrefix, then an empty string is returned.
//
// NOTE:
// - The sender address is set by the packet sender and may not have been validated a signature
// check if the packet sender isn't the interchain accounts module.
// - The sender address must only be used by modules on the sending chain.
func (iapd InterchainAccountPacketData) GetPacketSender(sourcePortID string) string {
icaOwner, found := strings.CutPrefix(sourcePortID, ControllerPortPrefix)
if !found {
return ""
}
return icaOwner
}
30 changes: 30 additions & 0 deletions modules/apps/27-interchain-accounts/types/packet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package types_test

import (
"github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/types"
ibctesting "github.com/cosmos/ibc-go/v7/testing"
)

var largeMemo = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum"
Expand Down Expand Up @@ -82,3 +83,32 @@ func (suite *TypesTestSuite) TestValidateBasic() {
})
}
}

func (suite *TypesTestSuite) TestGetPacketSender() {
testCases := []struct {
name string
srcPortID string
expSender string
}{
{
"success: port id has prefix",
types.ControllerPortPrefix + ibctesting.TestAccAddress,
ibctesting.TestAccAddress,
},
{
"failure: missing prefix",
ibctesting.TestAccAddress,
"",
},
{
"failure: empty port id",
"",
"",
},
}

for _, tc := range testCases {
packetData := types.InterchainAccountPacketData{}
suite.Require().Equal(tc.expSender, packetData.GetPacketSender(tc.srcPortID))
}
}
14 changes: 14 additions & 0 deletions modules/apps/transfer/types/packet.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"

ibcerrors "github.com/cosmos/ibc-go/v7/modules/core/errors"
ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported"
)

var _ ibcexported.PacketData = (*FungibleTokenPacketData)(nil)

var (
// DefaultRelativePacketTimeoutHeight is the default packet timeout height (in blocks) relative
// to the current block height of the counterparty chain provided by the client state. The
Expand Down Expand Up @@ -64,3 +67,14 @@ func (ftpd FungibleTokenPacketData) ValidateBasic() error {
func (ftpd FungibleTokenPacketData) GetBytes() []byte {
return sdk.MustSortJSON(mustProtoMarshalJSON(&ftpd))
}

// GetPacketSender returns the sender address of the packet data.
crodriguezvega marked this conversation as resolved.
Show resolved Hide resolved
//
// NOTE:
// - The sender address is set by the packet sender and may not have been
// validated a signature check if the packet sender isn't the transfer module.
// - The sender address must only be used by modules on the sending chain.
// - sourcePortID is not used in this implementation.
func (ftpd FungibleTokenPacketData) GetPacketSender(sourcePortID string) string {
return ftpd.Sender
}
12 changes: 12 additions & 0 deletions modules/apps/transfer/types/packet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,15 @@ func TestFungibleTokenPacketDataValidateBasic(t *testing.T) {
}
}
}

func (suite *TypesTestSuite) TestGetPacketSender() {
packetData := types.FungibleTokenPacketData{
Denom: denom,
Amount: amount,
Sender: sender,
Receiver: receiver,
Memo: "",
}

suite.Require().Equal(sender, packetData.GetPacketSender(types.PortID))
}
33 changes: 0 additions & 33 deletions modules/core/exported/channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,36 +17,3 @@ type CounterpartyChannelI interface {
GetChannelID() string
ValidateBasic() error
}

// PacketI defines the standard interface for IBC packets
type PacketI interface {
GetSequence() uint64
GetTimeoutHeight() Height
GetTimeoutTimestamp() uint64
GetSourcePort() string
GetSourceChannel() string
GetDestPort() string
GetDestChannel() string
GetData() []byte
ValidateBasic() error
}

// Acknowledgement defines the interface used to return acknowledgements in the OnRecvPacket callback.
// The Acknowledgement interface is used by core IBC to ensure partial state changes are not committed
// when packet receives have not properly succeeded (typically resulting in an error acknowledgement being returned).
// The interface also allows core IBC to obtain the acknowledgement bytes whose encoding is determined by each IBC application or middleware.
// Each custom acknowledgement type must implement this interface.
type Acknowledgement interface {
// Success determines if the IBC application state should be persisted when handling `RecvPacket`.
// During `OnRecvPacket` IBC application callback execution, all state changes are held in a cache store and committed if:
// - the acknowledgement.Success() returns true
// - a nil acknowledgement is returned (asynchronous acknowledgements)
//
// Note 1: IBC application callback events are always persisted so long as `RecvPacket` succeeds without error.
//
// Note 2: The return value should account for the success of the underlying IBC application or middleware. Thus the `acknowledgement.Success` is representative of the entire IBC stack's success when receiving a packet. The individual success of each acknowledgement associated with an IBC application or middleware must be determined by obtaining the actual acknowledgement type after decoding the acknowledgement bytes.
//
// See https://github.com/cosmos/ibc-go/blob/v7.0.0/docs/ibc/apps.md for further explanations.
Success() bool
Acknowledgement() []byte
}
41 changes: 41 additions & 0 deletions modules/core/exported/packet.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package exported

// PacketI defines the standard interface for IBC packets
type PacketI interface {
GetSequence() uint64
GetTimeoutHeight() Height
GetTimeoutTimestamp() uint64
GetSourcePort() string
GetSourceChannel() string
GetDestPort() string
GetDestChannel() string
GetData() []byte
ValidateBasic() error
}

// Acknowledgement defines the interface used to return acknowledgements in the OnRecvPacket callback.
// The Acknowledgement interface is used by core IBC to ensure partial state changes are not committed
// when packet receives have not properly succeeded (typically resulting in an error acknowledgement being returned).
// The interface also allows core IBC to obtain the acknowledgement bytes whose encoding is determined by each IBC application or middleware.
// Each custom acknowledgement type must implement this interface.
type Acknowledgement interface {
// Success determines if the IBC application state should be persisted when handling `RecvPacket`.
// During `OnRecvPacket` IBC application callback execution, all state changes are held in a cache store and committed if:
// - the acknowledgement.Success() returns true
// - a nil acknowledgement is returned (asynchronous acknowledgements)
//
// Note 1: IBC application callback events are always persisted so long as `RecvPacket` succeeds without error.
//
// Note 2: The return value should account for the success of the underlying IBC application or middleware. Thus the `acknowledgement.Success` is representative of the entire IBC stack's success when receiving a packet. The individual success of each acknowledgement associated with an IBC application or middleware must be determined by obtaining the actual acknowledgement type after decoding the acknowledgement bytes.
//
// See https://github.com/cosmos/ibc-go/blob/v7.0.0/docs/ibc/apps.md for further explanations.
Success() bool
Acknowledgement() []byte
}

// PacketData defines an optional interface which an application's packet data structure may implement.
type PacketData interface {
// GetPacketSender returns the sender address of the packet data.
// If the packet sender is unknown or undefined, an empty string should be returned.
GetPacketSender(sourcePortID string) string
colin-axner marked this conversation as resolved.
Show resolved Hide resolved
}