Skip to content

Commit

Permalink
feat: add FlagPrintEIP712MsgType
Browse files Browse the repository at this point in the history
  • Loading branch information
pythonberg1997 committed Sep 14, 2023
1 parent 3edf7eb commit 5a9e66e
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 9 deletions.
5 changes: 5 additions & 0 deletions client/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@ func ReadPersistentCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Cont
clientCtx = clientCtx.WithSimulation(dryRun)
}

if !clientCtx.Simulate || flagSet.Changed(flags.FlagPrintEIP712MsgType) {
printEIP712, _ := flagSet.GetBool(flags.FlagPrintEIP712MsgType)
clientCtx = clientCtx.WithSimulation(printEIP712).WithPrintEIP712MsgType(printEIP712)
}

if clientCtx.KeyringDir == "" || flagSet.Changed(flags.FlagKeyringDir) {
keyringDir, _ := flagSet.GetString(flags.FlagKeyringDir)

Expand Down
10 changes: 9 additions & 1 deletion client/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ type Context struct {
// IsAux is true when the signer is an auxiliary signer (e.g. the tipper).
IsAux bool

PrintEIP712MsgType bool

// TODO: Deprecated (remove).
LegacyAmino *codec.LegacyAmino
}
Expand Down Expand Up @@ -267,6 +269,12 @@ func (ctx Context) WithAux(isAux bool) Context {
return ctx
}

// WithPrintEIP712MsgType returns a copy of the context with an updated PrintEIP712MsgType value.
func (ctx Context) WithPrintEIP712MsgType(printEIP712MsgType bool) Context {
ctx.PrintEIP712MsgType = printEIP712MsgType
return ctx
}

// WithLedgerHasProto returns the context with the provided boolean value, indicating
// whether the target Ledger application can support Protobuf payloads.
func (ctx Context) WithLedgerHasProtobuf(val bool) Context {
Expand Down Expand Up @@ -369,7 +377,7 @@ func GetFromFields(clientCtx Context, kr keyring.Keyring, from string) (sdk.AccA
switch {
case clientCtx.Simulate:
if err != nil {
return nil, "", 0, fmt.Errorf("a valid bech32 address must be provided in simulation mode: %w", err)
return nil, "", 0, fmt.Errorf("a valid hex address must be provided in simulation mode: %w", err)
}

return addr, "", 0, nil
Expand Down
2 changes: 1 addition & 1 deletion client/context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ func TestGetFromFields(t *testing.T) {
},
from: "alice",
clientCtx: client.Context{}.WithSimulation(true),
expectedErr: "a valid bech32 address must be provided in simulation mode",
expectedErr: "a valid hex address must be provided in simulation mode",
},
{
keyring: func() keyring.Keyring {
Expand Down
3 changes: 3 additions & 0 deletions client/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ const (
// Tendermint logging flags
FlagLogLevel = "log_level"
FlagLogFormat = "log_format"

FlagPrintEIP712MsgType = "print-eip712-msg-type"
)

// LineBreak can be included in a command list to provide a blank line
Expand Down Expand Up @@ -136,6 +138,7 @@ func AddTxFlagsToCmd(cmd *cobra.Command) {
// --gas can accept integers and "auto"
f.String(FlagGas, "", fmt.Sprintf("gas limit to set per-transaction; set to %q to calculate sufficient gas automatically. Note: %q option doesn't always report accurate results. Set a valid coin value to adjust the result. Can be used instead of %q. (default %d)",
GasFlagAuto, GasFlagAuto, FlagFees, DefaultGasLimit))
f.Bool(FlagPrintEIP712MsgType, false, "ignore the --gas flag and perform a simulation of a transaction(but don't broadcast it) and print the EIP712 message type")

AddKeyringFlags(f)
}
Expand Down
87 changes: 82 additions & 5 deletions client/tx/factory.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package tx

import (
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"os"
Expand All @@ -15,11 +17,14 @@ import (
"github.com/cosmos/cosmos-sdk/client/flags"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/crypto/keys/eth/ethsecp256k1"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
"github.com/ethereum/go-ethereum/signer/core/apitypes"
)

// Factory defines a client transaction factory that facilitates generating and
Expand Down Expand Up @@ -80,8 +85,13 @@ func NewFactoryCLI(clientCtx client.Context, flagSet *pflag.FlagSet) (Factory, e
memo, _ := flagSet.GetString(flags.FlagNote)
timeoutHeight, _ := flagSet.GetUint64(flags.FlagTimeoutHeight)

gasStr, _ := flagSet.GetString(flags.FlagGas)
gasSetting, _ := flags.ParseGasSetting(gasStr)
var gasSetting flags.GasSetting
dryRun, _ := flagSet.GetBool(flags.FlagDryRun)
printEIP712MsgType, _ := flagSet.GetBool(flags.FlagPrintEIP712MsgType)
if !dryRun && !printEIP712MsgType {
gasStr, _ := flagSet.GetString(flags.FlagGas)
gasSetting, _ = flags.ParseGasSetting(gasStr)
}

f := Factory{
txConfig: clientCtx.TxConfig,
Expand Down Expand Up @@ -170,7 +180,7 @@ func (f Factory) WithFees(fees string) Factory {
}

// WithTips returns a copy of the Factory with an updated tip.
func (f Factory) WithTips(tip string, tipper string) Factory {
func (f Factory) WithTips(tip, tipper string) Factory {
parsedTips, err := sdk.ParseCoinsNormalized(tip)
if err != nil {
panic(err)
Expand Down Expand Up @@ -399,6 +409,73 @@ func (f Factory) PrintUnsignedTx(clientCtx client.Context, msgs ...sdk.Msg) erro
return clientCtx.PrintString(fmt.Sprintf("%s\n", json))
}

func (f Factory) PrintEIP712MsgType(clientCtx client.Context, msgs ...sdk.Msg) error {
if len(msgs) != 1 {
return errors.New("only one message is supported")
}

unsignedTx, err := f.BuildUnsignedTx(msgs...)
if err != nil {
return err
}

txRawBytes, err := clientCtx.TxConfig.TxEncoder()(unsignedTx.GetTx())
if err != nil {
return err
}
txRawBytesHex := hex.EncodeToString(txRawBytes)

signerData := authsigning.SignerData{
Address: clientCtx.From,
ChainID: clientCtx.ChainID,
}

chainID, err := sdk.ParseChainID(clientCtx.ChainID)
if err != nil {
return fmt.Errorf("failed to parse chainID: %s", err)
}
msgTypes, signDoc, err := authtx.GetMsgTypes(signerData, unsignedTx.GetTx(), chainID)
if err != nil {
return fmt.Errorf("failed to get msg types: %s", err)
}
typedData, err := authtx.WrapTxToTypedData(chainID.Uint64(), signDoc, msgTypes)
if err != nil {
return fmt.Errorf("failed to wrap tx to typedData: %s", err)
}

eip712MsgTypes := typedData.Types
delete(eip712MsgTypes, "Tx")
delete(eip712MsgTypes, "Fee")
delete(eip712MsgTypes, "Coin")
delete(eip712MsgTypes, "EIP712Domain")

msgData := typedData.Message["msg1"].(map[string]interface{})
if msgData == nil {
return fmt.Errorf("failed to get msg data")
}
msgTypeUrl := msgData["type"].(string)

type EIP712TypedData struct {
MsgTypeUrl string `json:"MsgTypeUrl"`
EIP712MessageType apitypes.Types `json:"EIP712MessageType"`
MessageData map[string]interface{} `json:"MessageData"`
TxRawBytes string `json:"TxRawBytes"`
}

eip712TypedData := EIP712TypedData{
MsgTypeUrl: msgTypeUrl,
EIP712MessageType: eip712MsgTypes,
MessageData: msgData,
TxRawBytes: txRawBytesHex,
}
bz, err := json.MarshalIndent(eip712TypedData, "", " ")
if err != nil {
return err
}

return clientCtx.PrintString(fmt.Sprintf("%s\n", bz))
}

// BuildSimTx creates an unsigned tx with an empty single signature and returns
// the encoded transaction or an error if the unsigned transaction cannot be
// built.
Expand Down Expand Up @@ -437,7 +514,7 @@ func (f Factory) BuildSimTx(msgs ...sdk.Msg) ([]byte, error) {
func (f Factory) getSimPK() (cryptotypes.PubKey, error) {
var (
ok bool
pk cryptotypes.PubKey = &secp256k1.PubKey{} // use default public key type
pk cryptotypes.PubKey = &ethsecp256k1.PubKey{} // use default public key type
)

// Use the first element from the list of keys in order to generate a valid
Expand Down
4 changes: 4 additions & 0 deletions client/tx/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ func GenerateOrBroadcastTxWithFactory(clientCtx client.Context, txf Factory, msg
return txf.PrintUnsignedTx(clientCtx, msgs...)
}

if clientCtx.PrintEIP712MsgType {
return txf.PrintEIP712MsgType(clientCtx, msgs...)
}

return BroadcastTx(clientCtx, txf, msgs...)
}

Expand Down
4 changes: 2 additions & 2 deletions x/bank/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func NewSendTxCmd() *cobra.Command {
Short: "Send funds from one account to another.",
Long: `Send funds from one account to another.
Note, the '--from' flag is ignored as it is implied from [from_key_or_address].
When using '--dry-run' a key name cannot be used, only a bech32 address.
When using '--dry-run' a key name cannot be used, only a hex address.
`,
Args: cobra.ExactArgs(3),
RunE: func(cmd *cobra.Command, args []string) error {
Expand Down Expand Up @@ -80,7 +80,7 @@ func NewMultiSendTxCmd() *cobra.Command {
By default, sends the [amount] to each address of the list.
Using the '--split' flag, the [amount] is split equally between the addresses.
Note, the '--from' flag is ignored as it is implied from [from_key_or_address].
When using '--dry-run' a key name cannot be used, only a bech32 address.
When using '--dry-run' a key name cannot be used, only a hex address.
`,
Args: cobra.MinimumNArgs(4),
RunE: func(cmd *cobra.Command, args []string) error {
Expand Down

0 comments on commit 5a9e66e

Please sign in to comment.