-
Notifications
You must be signed in to change notification settings - Fork 723
feat: added ics27-2 gmp application #8352
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
Draft
srdtrk
wants to merge
49
commits into
main
Choose a base branch
from
serdar/xxx-contract-calls
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
49 commits
Select commit
Hold shift + click to select a range
2b8ebde
feat: added proto types
srdtrk e64d4b8
chore: ran proto-all
srdtrk 33760e8
Merge branch 'main' into serdar/xxx-contract-calls
srdtrk 7f98428
chore: generate proto
srdtrk 2b29b85
imp: added type helpers
srdtrk 5b198c7
imp: added new proto
srdtrk c7289d5
imp: added query.proto
srdtrk add062d
Merge branch 'main' into serdar/xxx-contract-calls
srdtrk 83be763
chore: gen proto types
srdtrk 0394e66
imp: regen proto
srdtrk 0f5dbfb
imp: save progress
srdtrk 4fed4b9
feat: implemented basic module with autocli
srdtrk 2d21a1e
imp: added ibc boilerplate
srdtrk 7dfb3e6
feat: add module to simapp
srdtrk 5cd5bce
imp: added account keeper
srdtrk d0a7742
imp: remoce ics4wrapper
srdtrk 918f808
imp: implemented first message server
srdtrk 23366e8
imp: verify autocli
srdtrk 230ef6a
imp: implemented OnSendPacket
srdtrk 032dd63
imp: implemented ack and timeout entry points
srdtrk 707fa58
imp: more boilerplate
srdtrk 06495a4
imp: added ack to proto
srdtrk eceb5b1
imp: added ack helpers
srdtrk 2bd764d
imp: more boilerplate
srdtrk d3a9cd9
feat: added account gen
srdtrk 0fab11f
imp: added cosmos tx
srdtrk 134b82a
imp: implemented receive
srdtrk ef9559a
imp: implemented query
srdtrk fa61151
lint
srdtrk 0926c7d
imp: added gmp to wasm simapp
srdtrk c6203a9
style: lint
srdtrk 18c8157
style: lint
srdtrk be8367e
chore: bump go version
srdtrk 7df1aab
Merge branch 'main' into serdar/xxx-contract-calls
srdtrk ee75f8b
imp: attempt to improve module wiring
srdtrk e6c856e
imp: fix attempt
srdtrk d84336d
imp: removed gmp from unused simapp
srdtrk cc9968d
fix: keeper wiring
srdtrk a841ca9
imp: allow receiver to be empty
srdtrk 62159d4
imp: added logger
srdtrk 6151f8f
imp: no err if acc already exists
srdtrk c29bc05
merge: branch 'main' into serdar/xxx-contract-calls
srdtrk 09a7f9a
deps: go mod tidy
srdtrk 4dd15cf
fix: compiler problems
srdtrk 12126c9
imp: allow protojson
srdtrk d389a66
imp: added NewMsgSendCall
srdtrk 0c440fd
lint: issues
srdtrk 908ecbe
docs: add PICKUP to gmp
johnnylarner c9a2f3c
docs: added pickup doc
srdtrk File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# GMP pickup document | ||
|
||
`27-gmp` application is feature complete, however, it is not yet production ready. This document outlines the remaining tasks to make it production ready. | ||
|
||
- `BuildAddressPredictable` should be audited and tested for security. Specifcally, what happens if the address was created by sending the address some coins first? | ||
- `DeserializeCosmosTx` supports both protobuf encoding and protojson encoding. However, the support for this is hacky since it tries to decode the tx using both methods and returns the one that works. It would be better to have a more robust way to determine the encoding of the tx. | ||
- Add unit tests and integration tests for the `27-gmp` module. Right now, there are no tests for this module. | ||
- End to end tests should be added to ensure the entire flow works as expected. End to end tests should be added to this repository if Cosmos to Cosmos calls are to be supported, otherwise, the end to end tests in the `solidity-ibc-go` repository should be sufficient. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
package gmp | ||
|
||
import ( | ||
"fmt" | ||
|
||
errorsmod "cosmossdk.io/errors" | ||
|
||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
|
||
"github.com/cosmos/ibc-go/v10/modules/apps/27-gmp/keeper" | ||
"github.com/cosmos/ibc-go/v10/modules/apps/27-gmp/types" | ||
clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" | ||
channeltypesv2 "github.com/cosmos/ibc-go/v10/modules/core/04-channel/v2/types" | ||
"github.com/cosmos/ibc-go/v10/modules/core/api" | ||
ibcerrors "github.com/cosmos/ibc-go/v10/modules/core/errors" | ||
) | ||
|
||
var _ api.IBCModule = (*IBCModule)(nil) | ||
|
||
// IBCModule implements the ICS26 interface for transfer given the transfer keeper. | ||
type IBCModule struct { | ||
keeper *keeper.Keeper | ||
} | ||
|
||
// NewIBCModule creates a new IBCModule given the keeper | ||
func NewIBCModule(k *keeper.Keeper) *IBCModule { | ||
return &IBCModule{ | ||
keeper: k, | ||
} | ||
} | ||
|
||
func (*IBCModule) OnSendPacket(ctx sdk.Context, sourceChannel string, destinationChannel string, sequence uint64, payload channeltypesv2.Payload, signer sdk.AccAddress) error { | ||
if payload.SourcePort != types.PortID || payload.DestinationPort != types.PortID { | ||
return errorsmod.Wrapf(channeltypesv2.ErrInvalidPacket, "payload port ID is invalid: expected %s, got sourcePort: %s destPort: %s", types.PortID, payload.SourcePort, payload.DestinationPort) | ||
} | ||
if !clienttypes.IsValidClientID(sourceChannel) || !clienttypes.IsValidClientID(destinationChannel) { | ||
return errorsmod.Wrapf(channeltypesv2.ErrInvalidPacket, "client IDs must be in valid format: {string}-{number}") | ||
} | ||
|
||
data, err := types.UnmarshalPacketData(payload.Value, payload.Version, payload.Encoding) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if err := data.ValidateBasic(); err != nil { | ||
return errorsmod.Wrapf(err, "failed to validate %s packet data", types.Version) | ||
} | ||
|
||
sender, err := sdk.AccAddressFromBech32(data.Sender) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if !signer.Equals(sender) { | ||
return errorsmod.Wrapf(ibcerrors.ErrUnauthorized, "sender %s is different from signer %s", sender, signer) | ||
} | ||
|
||
// TODO: emit event and telemetry | ||
|
||
return nil | ||
} | ||
|
||
func (im *IBCModule) OnRecvPacket(ctx sdk.Context, sourceChannel, destinationChannel string, sequence uint64, payload channeltypesv2.Payload, relayer sdk.AccAddress) channeltypesv2.RecvPacketResult { | ||
if payload.SourcePort != types.PortID || payload.DestinationPort != types.PortID { | ||
return channeltypesv2.RecvPacketResult{ | ||
Status: channeltypesv2.PacketStatus_Failure, | ||
} | ||
} | ||
if payload.Version != types.Version { | ||
return channeltypesv2.RecvPacketResult{ | ||
Status: channeltypesv2.PacketStatus_Failure, | ||
} | ||
} | ||
|
||
packetData, ackErr := types.UnmarshalPacketData(payload.Value, payload.Version, payload.Encoding) | ||
if ackErr != nil { | ||
im.keeper.Logger(ctx).Error(fmt.Sprintf("%s sequence %d", ackErr.Error(), sequence)) | ||
return channeltypesv2.RecvPacketResult{ | ||
Status: channeltypesv2.PacketStatus_Failure, | ||
} | ||
} | ||
|
||
if ackErr := packetData.ValidateBasic(); ackErr != nil { | ||
im.keeper.Logger(ctx).Error(fmt.Sprintf("%s sequence %d", ackErr.Error(), sequence)) | ||
return channeltypesv2.RecvPacketResult{ | ||
Status: channeltypesv2.PacketStatus_Failure, | ||
} | ||
} | ||
|
||
result, ackErr := im.keeper.OnRecvPacket( | ||
ctx, | ||
packetData, | ||
payload.SourcePort, | ||
sourceChannel, | ||
payload.DestinationPort, | ||
destinationChannel, | ||
) | ||
if ackErr != nil { | ||
im.keeper.Logger(ctx).Error(fmt.Sprintf("%s sequence %d", ackErr.Error(), sequence)) | ||
return channeltypesv2.RecvPacketResult{ | ||
Status: channeltypesv2.PacketStatus_Failure, | ||
} | ||
} | ||
|
||
ack := types.NewAcknowledgement(result) | ||
ackBz, ackErr := types.MarshalAcknowledgement(&ack, types.Version, payload.Encoding) | ||
if ackErr != nil { | ||
im.keeper.Logger(ctx).Error(fmt.Sprintf("%s sequence %d", ackErr.Error(), sequence)) | ||
return channeltypesv2.RecvPacketResult{ | ||
Status: channeltypesv2.PacketStatus_Failure, | ||
} | ||
} | ||
|
||
im.keeper.Logger(ctx).Info("successfully handled ICS-27 GMP packet", "sequence", sequence) | ||
|
||
// TODO: implement telemetry | ||
|
||
return channeltypesv2.RecvPacketResult{ | ||
Status: channeltypesv2.PacketStatus_Success, | ||
Acknowledgement: ackBz, | ||
} | ||
} | ||
|
||
func (*IBCModule) OnTimeoutPacket(_ sdk.Context, _, _ string, _ uint64, _ channeltypesv2.Payload, _ sdk.AccAddress) error { | ||
return nil | ||
} | ||
|
||
func (*IBCModule) OnAcknowledgementPacket(_ sdk.Context, _, _ string, _ uint64, _ []byte, _ channeltypesv2.Payload, _ sdk.AccAddress) error { | ||
return nil | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package keeper | ||
|
||
import ( | ||
"context" | ||
|
||
"cosmossdk.io/collections" | ||
errorsmod "cosmossdk.io/errors" | ||
|
||
"github.com/cosmos/ibc-go/v10/modules/apps/27-gmp/types" | ||
) | ||
|
||
// getOrCreateICS27Account retrieves an existing ICS27 account or creates a new one if it doesn't exist. | ||
func (k *Keeper) getOrCreateICS27Account(ctx context.Context, accountID *types.AccountIdentifier) (*types.ICS27Account, error) { | ||
existingIcs27Account, err := k.Accounts.Get(ctx, collections.Join3(accountID.ClientId, accountID.Sender, accountID.Salt)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do you have this additional storage out of state? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems redundant with accountKeeper |
||
if err == nil { | ||
return &existingIcs27Account, nil | ||
} else if !errorsmod.IsOf(err, collections.ErrNotFound) { | ||
return nil, err | ||
} | ||
|
||
// Create a new account | ||
newAddr, err := types.BuildAddressPredictable(accountID) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
existingAcc := k.accountKeeper.GetAccount(ctx, newAddr) | ||
if existingAcc != nil { | ||
// TODO: ensure this cannot be abused (refactor after this is resolved) | ||
ics27Account := types.NewICS27Account(existingAcc.GetAddress().String(), accountID) | ||
if err := k.Accounts.Set(ctx, collections.Join3(accountID.ClientId, accountID.Sender, accountID.Salt), ics27Account); err != nil { | ||
return nil, errorsmod.Wrapf(err, "failed to set account %s in store", ics27Account) | ||
} | ||
|
||
return &ics27Account, nil | ||
} | ||
|
||
newAcc := k.accountKeeper.NewAccountWithAddress(ctx, newAddr) | ||
k.accountKeeper.SetAccount(ctx, newAcc) | ||
|
||
ics27Account := types.NewICS27Account(newAcc.GetAddress().String(), accountID) | ||
if err := k.Accounts.Set(ctx, collections.Join3(accountID.ClientId, accountID.Sender, accountID.Salt), ics27Account); err != nil { | ||
return nil, errorsmod.Wrapf(err, "failed to set account %s in store", ics27Account) | ||
} | ||
|
||
k.Logger(ctx).Info("Created new ICS27 account", "account", ics27Account) | ||
return &ics27Account, nil | ||
} | ||
|
||
// getOrComputeICS27Adderss retrieves an existing ICS27 account address or computes it if it doesn't exist. This doesn't modify the store. | ||
func (k *Keeper) getOrComputeICS27Address(ctx context.Context, accountID *types.AccountIdentifier) (string, error) { | ||
existingIcs27Account, err := k.Accounts.Get(ctx, collections.Join3(accountID.ClientId, accountID.Sender, accountID.Salt)) | ||
if err == nil { | ||
return existingIcs27Account.Address, nil | ||
} else if !errorsmod.IsOf(err, collections.ErrNotFound) { | ||
return "", err | ||
} | ||
|
||
// Compute a new address | ||
newAddr, err := types.BuildAddressPredictable(accountID) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
return newAddr.String(), nil | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package keeper | ||
|
||
import ( | ||
"context" | ||
|
||
"cosmossdk.io/collections" | ||
errorsmod "cosmossdk.io/errors" | ||
|
||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
|
||
"github.com/cosmos/ibc-go/v10/modules/apps/27-gmp/types" | ||
ibcerrors "github.com/cosmos/ibc-go/v10/modules/core/errors" | ||
) | ||
|
||
// InitGenesis initializes the module state from a genesis state. | ||
func (k *Keeper) InitGenesis(ctx context.Context, data *types.GenesisState) error { | ||
for _, account := range data.Ics27Accounts { | ||
if _, err := sdk.AccAddressFromBech32(account.AccountAddress); err != nil { | ||
return errorsmod.Wrapf(ibcerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) | ||
} | ||
if _, err := sdk.AccAddressFromBech32(account.AccountId.Sender); err != nil { | ||
return errorsmod.Wrapf(ibcerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) | ||
} | ||
|
||
if err := k.Accounts.Set(ctx, collections.Join3(account.AccountId.ClientId, account.AccountId.Sender, account.AccountId.Salt), types.ICS27Account{ | ||
Address: account.AccountAddress, | ||
AccountId: &account.AccountId, | ||
}); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// ExportGenesis exports the module state to a genesis state. | ||
func (k *Keeper) ExportGenesis(ctx context.Context) (*types.GenesisState, error) { | ||
var accounts []types.RegisteredICS27Account | ||
if err := k.Accounts.Walk(ctx, nil, func(key collections.Triple[string, string, []byte], value types.ICS27Account) (bool, error) { | ||
accounts = append(accounts, types.RegisteredICS27Account{ | ||
AccountAddress: value.Address, | ||
AccountId: *value.AccountId, | ||
}) | ||
|
||
return false, nil | ||
}); err != nil { | ||
return nil, err | ||
} | ||
|
||
return &types.GenesisState{ | ||
Ics27Accounts: accounts, | ||
}, nil | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package keeper | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"strings" | ||
|
||
"cosmossdk.io/collections" | ||
storetypes "cosmossdk.io/core/store" | ||
"cosmossdk.io/log" | ||
|
||
"github.com/cosmos/cosmos-sdk/codec" | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
|
||
"github.com/cosmos/ibc-go/v10/modules/apps/27-gmp/types" | ||
"github.com/cosmos/ibc-go/v10/modules/core/exported" | ||
) | ||
|
||
// Keeper defines the IBC fungible transfer keeper | ||
type Keeper struct { | ||
cdc codec.Codec | ||
|
||
msgRouter types.MessageRouter | ||
|
||
accountKeeper types.AccountKeeper | ||
|
||
// the address capable of executing a MsgUpdateParams message. Typically, this | ||
// should be the x/gov module account. | ||
authority string | ||
|
||
// state management | ||
Schema collections.Schema | ||
// Accounts is a map of (ClientID, Sender, Salt) to ICS27Account | ||
Accounts collections.Map[collections.Triple[string, string, []byte], types.ICS27Account] | ||
} | ||
|
||
// NewKeeper creates a new Keeper instance | ||
func NewKeeper( | ||
cdc codec.Codec, storeService storetypes.KVStoreService, | ||
accountKeeper types.AccountKeeper, msgRouter types.MessageRouter, | ||
authority string, | ||
) *Keeper { | ||
if strings.TrimSpace(authority) == "" { | ||
panic(errors.New("authority must be non-empty")) | ||
} | ||
|
||
sb := collections.NewSchemaBuilder(storeService) | ||
k := Keeper{ | ||
cdc: cdc, | ||
msgRouter: msgRouter, | ||
accountKeeper: accountKeeper, | ||
authority: authority, | ||
Accounts: collections.NewMap(sb, types.AccountsKey, "accounts", collections.TripleKeyCodec(collections.StringKey, collections.StringKey, collections.BytesKey), codec.CollValue[types.ICS27Account](cdc)), | ||
} | ||
|
||
schema, err := sb.Build() | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
k.Schema = schema | ||
|
||
return &k | ||
} | ||
|
||
// GetAuthority returns the module's authority. | ||
func (k *Keeper) GetAuthority() string { | ||
return k.authority | ||
} | ||
|
||
// Logger returns a module-specific logger. | ||
func (*Keeper) Logger(goCtx context.Context) log.Logger { | ||
return sdk.UnwrapSDKContext(goCtx).Logger().With("module", "x/"+exported.ModuleName+"-"+types.ModuleName) | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this check exist in
SendPacket