Skip to content

Commit

Permalink
feat: add MsgExecCompat
Browse files Browse the repository at this point in the history
* ExecCompat has same functionality as Exec but accepts array of json-encoded message string instead of []*Any
* Resolves issues with EIP712 signing
  • Loading branch information
gorgos committed Jan 15, 2025
1 parent 78a5641 commit d4006e2
Show file tree
Hide file tree
Showing 6 changed files with 579 additions and 84 deletions.
4 changes: 4 additions & 0 deletions proto/cosmos/tx/signing/v1beta1/signing.proto
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ enum SignMode {
// Amino JSON and will be removed in the future.
SIGN_MODE_LEGACY_AMINO_JSON = 127;

// Injective EIP712 support for any cosmos messages which uses proto-json encoded string for messages
// Signature verification is implemented in injective core
SIGN_MODE_EIP712_V2 = 128;

// SIGN_MODE_EIP_191 specifies the sign mode for EIP 191 signing on the Cosmos
// SDK. Ref: https://eips.ethereum.org/EIPS/eip-191
//
Expand Down
78 changes: 42 additions & 36 deletions types/tx/signing/signing.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions x/authz/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ func RegisterLegacyAminoCodec(registrar registry.AminoRegistrar) {
legacy.RegisterAminoMsg(registrar, &MsgGrant{}, "cosmos-sdk/MsgGrant")
legacy.RegisterAminoMsg(registrar, &MsgRevoke{}, "cosmos-sdk/MsgRevoke")
legacy.RegisterAminoMsg(registrar, &MsgExec{}, "cosmos-sdk/MsgExec")
legacy.RegisterAminoMsg(registrar, &MsgExecCompat{}, "cosmos-sdk/MsgExecCompat")

registrar.RegisterInterface((*Authorization)(nil), nil)
registrar.RegisterConcrete(&GenericAuthorization{}, "cosmos-sdk/GenericAuthorization")
Expand All @@ -27,6 +28,7 @@ func RegisterInterfaces(registrar registry.InterfaceRegistrar) {
&MsgGrant{},
&MsgRevoke{},
&MsgExec{},
&MsgExecCompat{},
)

// since bank.SendAuthorization and staking.StakeAuthorization both implement Authorization
Expand Down
44 changes: 44 additions & 0 deletions x/authz/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package keeper
import (
"context"
"errors"
"fmt"
"strings"

errorsmod "cosmossdk.io/errors"
Expand Down Expand Up @@ -131,6 +132,49 @@ func (k Keeper) Exec(ctx context.Context, msg *authz.MsgExec) (*authz.MsgExecRes
return &authz.MsgExecResponse{Results: results}, nil
}

// Exec implements the MsgServer.ExecCompat method.
func (k Keeper) ExecCompat(goCtx context.Context, msg *authz.MsgExecCompat) (*authz.MsgExecCompatResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

grantee, err := k.authKeeper.AddressCodec().StringToBytes(msg.Grantee)
if err != nil {
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid grantee address: %s", err)
}

if len(msg.Msgs) == 0 {
return nil, sdkerrors.ErrInvalidRequest.Wrapf("messages cannot be empty")
}

subMsgs := make([]sdk.Msg, len(msg.Msgs))
for idx, m := range msg.Msgs {
var iMsg sdk.Msg
err := k.cdc.UnmarshalInterfaceJSON([]byte(m), &iMsg)
if err != nil {
return nil, fmt.Errorf("parse message at index %d error: %w", idx, err)
}

m, ok := iMsg.(sdk.HasValidateBasic)
if !ok {
subMsgs[idx] = iMsg
continue
}

err = m.ValidateBasic()
if err != nil {
return nil, fmt.Errorf("validate message at index %d error: %w", idx, err)
}

subMsgs[idx] = iMsg
}

results, err := k.DispatchActions(ctx, grantee, subMsgs)
if err != nil {
return nil, fmt.Errorf("dispatch err: %w", err)
}

return &authz.MsgExecCompatResponse{Results: results}, nil
}

func (k Keeper) PruneExpiredGrants(ctx context.Context, msg *authz.MsgPruneExpiredGrants) (*authz.MsgPruneExpiredGrantsResponse, error) {
// 75 is an arbitrary value, we can change it later if needed
if err := k.DequeueAndDeleteExpiredGrants(ctx, 75); err != nil {
Expand Down
17 changes: 17 additions & 0 deletions x/authz/proto/cosmos/authz/v1beta1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ service Msg {
rpc PruneExpiredGrants(MsgPruneExpiredGrants) returns (MsgPruneExpiredGrantsResponse) {
option (cosmos_proto.method_added_in) = "cosmos-sdk 0.51";
}

// ExecCompat has same functionality as Exec but accepts array of json-encoded message string instead of []*Any. Resolves issues with EIP712 signing.
rpc ExecCompat(MsgExecCompat) returns (MsgExecCompatResponse);
}

// MsgGrant is a request type for Grant method. It declares authorization to the grantee
Expand Down Expand Up @@ -90,6 +93,11 @@ message MsgRevoke {
// MsgRevokeResponse defines the Msg/MsgRevokeResponse response type.
message MsgRevokeResponse {}

// MsgExecCompatResponse defines the Msg/MsgExecCompatResponse response type.
message MsgExecCompatResponse {
repeated bytes results = 1;
}

// MsgRevokeAll revokes all grants issued by the specified granter.
message MsgRevokeAll {
option (cosmos_proto.message_added_in) = "cosmos-sdk 0.51";
Expand All @@ -116,3 +124,12 @@ message MsgPruneExpiredGrants {
message MsgPruneExpiredGrantsResponse {
option (cosmos_proto.message_added_in) = "x/authz v0.2.0";
}

// MsgExecCompat supports legacy amino codec for frontend metamask signing
// Functions are same as MsgExec, but input for msgs is array of strings
message MsgExecCompat {
option (cosmos.msg.v1.signer) = "grantee";
option (amino.name) = "cosmos-sdk/MsgExec";
string grantee = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
repeated string msgs = 2;
}
Loading

0 comments on commit d4006e2

Please sign in to comment.