forked from cerc-io/laconicd-deprecated
Add EIP-712 encoding support type for any array (#1430)
* Add EIP-712 encoding support type for any array * Refactor implementation + add tests * Refactor unpacking implementation; refactor test case * Fix lint issue * Add MsgExec test case * Update comment for clarity * Add changelog entry * Refactor `sdkerrors` to `errorsmod` Co-authored-by: Freddy Caceres <facs95@gmail.com>
This commit is contained in:
parent
71e51aabf6
commit
5f418c74ef
@ -45,6 +45,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
|||||||
* (deps) [#1168](https://github.com/evmos/ethermint/pull/1168) Upgrade Cosmos SDK to `v0.46`.
|
* (deps) [#1168](https://github.com/evmos/ethermint/pull/1168) Upgrade Cosmos SDK to `v0.46`.
|
||||||
* (feemarket) [#1194](https://github.com/evmos/ethermint/pull/1194) Apply feemarket to native cosmos tx.
|
* (feemarket) [#1194](https://github.com/evmos/ethermint/pull/1194) Apply feemarket to native cosmos tx.
|
||||||
* (eth) [#1346](https://github.com/evmos/ethermint/pull/1346) Added support for `sdk.Dec` and `ed25519` type on eip712.
|
* (eth) [#1346](https://github.com/evmos/ethermint/pull/1346) Added support for `sdk.Dec` and `ed25519` type on eip712.
|
||||||
|
* (eth) [#1430](https://github.com/evmos/ethermint/pull/1430) Added support for array of type `Any` on eip712.
|
||||||
* (ante) [1460](https://github.com/evmos/ethermint/pull/1460) Add KV Gas config on ethereum Txs.
|
* (ante) [1460](https://github.com/evmos/ethermint/pull/1460) Add KV Gas config on ethereum Txs.
|
||||||
* (geth) [#1413](https://github.com/evmos/ethermint/pull/1413) Update geth version to v1.10.25.
|
* (geth) [#1413](https://github.com/evmos/ethermint/pull/1413) Update geth version to v1.10.25.
|
||||||
|
|
||||||
|
@ -409,7 +409,29 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
|||||||
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
|
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
|
||||||
amount := sdk.NewCoins(coinAmount)
|
amount := sdk.NewCoins(coinAmount)
|
||||||
gas := uint64(200000)
|
gas := uint64(200000)
|
||||||
txBuilder := suite.CreateTestEIP712MsgEditValidator(from, privKey, "ethermint_9000-1", gas, amount)
|
txBuilder := suite.CreateTestEIP712MsgSubmitEvidence(from, privKey, "ethermint_9000-1", gas, amount)
|
||||||
|
return txBuilder.GetTx()
|
||||||
|
}, false, false, true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"success- DeliverTx EIP712 submit proposal v1",
|
||||||
|
func() sdk.Tx {
|
||||||
|
from := acc.GetAddress()
|
||||||
|
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
|
||||||
|
amount := sdk.NewCoins(coinAmount)
|
||||||
|
gas := uint64(200000)
|
||||||
|
txBuilder := suite.CreateTestEIP712SubmitProposalV1(from, privKey, "ethermint_9000-1", gas, amount)
|
||||||
|
return txBuilder.GetTx()
|
||||||
|
}, false, false, true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"success- DeliverTx EIP712 MsgExec",
|
||||||
|
func() sdk.Tx {
|
||||||
|
from := acc.GetAddress()
|
||||||
|
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
|
||||||
|
amount := sdk.NewCoins(coinAmount)
|
||||||
|
gas := uint64(200000)
|
||||||
|
txBuilder := suite.CreateTestEIP712MsgExec(from, privKey, "ethermint_9000-1", gas, amount)
|
||||||
return txBuilder.GetTx()
|
return txBuilder.GetTx()
|
||||||
}, false, false, true,
|
}, false, false, true,
|
||||||
},
|
},
|
||||||
|
@ -38,12 +38,14 @@ import (
|
|||||||
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||||
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||||
|
authz "github.com/cosmos/cosmos-sdk/x/authz"
|
||||||
cryptocodec "github.com/evmos/ethermint/crypto/codec"
|
cryptocodec "github.com/evmos/ethermint/crypto/codec"
|
||||||
"github.com/evmos/ethermint/crypto/ethsecp256k1"
|
"github.com/evmos/ethermint/crypto/ethsecp256k1"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||||
evtypes "github.com/cosmos/cosmos-sdk/x/evidence/types"
|
evtypes "github.com/cosmos/cosmos-sdk/x/evidence/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/feegrant"
|
"github.com/cosmos/cosmos-sdk/x/feegrant"
|
||||||
|
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
|
||||||
types5 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
types5 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
||||||
"github.com/evmos/ethermint/app"
|
"github.com/evmos/ethermint/app"
|
||||||
ante "github.com/evmos/ethermint/app/ante"
|
ante "github.com/evmos/ethermint/app/ante"
|
||||||
@ -344,6 +346,52 @@ func (suite *AnteTestSuite) CreateTestEIP712MsgSubmitEvidence(from sdk.AccAddres
|
|||||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgEvidence)
|
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgEvidence)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (suite *AnteTestSuite) CreateTestEIP712SubmitProposalV1(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||||
|
// Build V1 proposal messages. Must all be same-type, since EIP-712
|
||||||
|
// does not support arrays of variable type.
|
||||||
|
authAcc := suite.app.GovKeeper.GetGovernanceAccount(suite.ctx)
|
||||||
|
|
||||||
|
proposal1, ok := types5.ContentFromProposalType("My proposal 1", "My description 1", types5.ProposalTypeText)
|
||||||
|
suite.Require().True(ok)
|
||||||
|
content1, err := govtypes.NewLegacyContent(
|
||||||
|
proposal1,
|
||||||
|
sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), authAcc.GetAddress().Bytes()),
|
||||||
|
)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
proposal2, ok := types5.ContentFromProposalType("My proposal 2", "My description 2", types5.ProposalTypeText)
|
||||||
|
suite.Require().True(ok)
|
||||||
|
content2, err := govtypes.NewLegacyContent(
|
||||||
|
proposal2,
|
||||||
|
sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), authAcc.GetAddress().Bytes()),
|
||||||
|
)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
proposalMsgs := []sdk.Msg{
|
||||||
|
content1,
|
||||||
|
content2,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build V1 proposal
|
||||||
|
msgProposal, err := govtypes.NewMsgSubmitProposal(
|
||||||
|
proposalMsgs,
|
||||||
|
sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(100))),
|
||||||
|
sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), from.Bytes()),
|
||||||
|
"Metadata",
|
||||||
|
)
|
||||||
|
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgProposal)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *AnteTestSuite) CreateTestEIP712MsgExec(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||||
|
recipient := sdk.AccAddress(common.Address{}.Bytes())
|
||||||
|
msgSend := types2.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewInt(1))))
|
||||||
|
msgExec := authz.NewMsgExec(from, []sdk.Msg{msgSend})
|
||||||
|
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, &msgExec)
|
||||||
|
}
|
||||||
|
|
||||||
// StdSignBytes returns the bytes to sign for a transaction.
|
// StdSignBytes returns the bytes to sign for a transaction.
|
||||||
func StdSignBytes(cdc *codec.LegacyAmino, chainID string, accnum uint64, sequence uint64, timeout uint64, fee legacytx.StdFee, msgs []sdk.Msg, memo string, tip *txtypes.Tip) []byte {
|
func StdSignBytes(cdc *codec.LegacyAmino, chainID string, accnum uint64, sequence uint64, timeout uint64, fee legacytx.StdFee, msgs []sdk.Msg, memo string, tip *txtypes.Tip) []byte {
|
||||||
msgsBytes := make([]json.RawMessage, 0, len(msgs))
|
msgsBytes := make([]json.RawMessage, 0, len(msgs))
|
||||||
|
@ -188,7 +188,11 @@ func traverseFields(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
var field reflect.Value
|
var (
|
||||||
|
field reflect.Value
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
if v.IsValid() {
|
if v.IsValid() {
|
||||||
field = v.Field(i)
|
field = v.Field(i)
|
||||||
}
|
}
|
||||||
@ -197,23 +201,10 @@ func traverseFields(
|
|||||||
fieldName := jsonNameFromTag(t.Field(i).Tag)
|
fieldName := jsonNameFromTag(t.Field(i).Tag)
|
||||||
|
|
||||||
if fieldType == cosmosAnyType {
|
if fieldType == cosmosAnyType {
|
||||||
any, ok := field.Interface().(*codectypes.Any)
|
// Unpack field, value as Any
|
||||||
if !ok {
|
if fieldType, field, err = unpackAny(cdc, field); err != nil {
|
||||||
return errorsmod.Wrapf(errortypes.ErrPackAny, "%T", field.Interface())
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
anyWrapper := &cosmosAnyWrapper{
|
|
||||||
Type: any.TypeUrl,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := cdc.UnpackAny(any, &anyWrapper.Value); err != nil {
|
|
||||||
return errorsmod.Wrap(err, "failed to unpack Any in msg struct")
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldType = reflect.TypeOf(anyWrapper)
|
|
||||||
field = reflect.ValueOf(anyWrapper)
|
|
||||||
|
|
||||||
// then continue as normal
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If its a nil pointer, do not include in types
|
// If its a nil pointer, do not include in types
|
||||||
@ -255,6 +246,12 @@ func traverseFields(
|
|||||||
fieldType = fieldType.Elem()
|
fieldType = fieldType.Elem()
|
||||||
field = field.Index(0)
|
field = field.Index(0)
|
||||||
isCollection = true
|
isCollection = true
|
||||||
|
|
||||||
|
if fieldType == cosmosAnyType {
|
||||||
|
if fieldType, field, err = unpackAny(cdc, field); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
@ -345,6 +342,27 @@ func jsonNameFromTag(tag reflect.StructTag) string {
|
|||||||
return parts[0]
|
return parts[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unpack the given Any value with Type/Value deconstruction
|
||||||
|
func unpackAny(cdc codectypes.AnyUnpacker, field reflect.Value) (reflect.Type, reflect.Value, error) {
|
||||||
|
any, ok := field.Interface().(*codectypes.Any)
|
||||||
|
if !ok {
|
||||||
|
return nil, reflect.Value{}, errorsmod.Wrapf(errortypes.ErrPackAny, "%T", field.Interface())
|
||||||
|
}
|
||||||
|
|
||||||
|
anyWrapper := &cosmosAnyWrapper{
|
||||||
|
Type: any.TypeUrl,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cdc.UnpackAny(any, &anyWrapper.Value); err != nil {
|
||||||
|
return nil, reflect.Value{}, errorsmod.Wrap(err, "failed to unpack Any in msg struct")
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldType := reflect.TypeOf(anyWrapper)
|
||||||
|
field = reflect.ValueOf(anyWrapper)
|
||||||
|
|
||||||
|
return fieldType, field, nil
|
||||||
|
}
|
||||||
|
|
||||||
// _.foo_bar.baz -> TypeFooBarBaz
|
// _.foo_bar.baz -> TypeFooBarBaz
|
||||||
//
|
//
|
||||||
// this is needed for Geth's own signing code which doesn't
|
// this is needed for Geth's own signing code which doesn't
|
||||||
|
Loading…
Reference in New Issue
Block a user