2020-04-01 18:49:21 +00:00
package ante_test
import (
2022-09-17 13:37:47 +00:00
"encoding/json"
"fmt"
2022-03-11 10:31:16 +00:00
"math"
2022-05-31 16:28:46 +00:00
"math/big"
2022-03-11 10:31:16 +00:00
"testing"
"time"
2022-07-28 13:43:49 +00:00
sdkmath "cosmossdk.io/math"
"github.com/stretchr/testify/suite"
2022-02-26 16:34:43 +00:00
"github.com/cosmos/cosmos-sdk/codec"
2022-07-28 13:43:49 +00:00
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
2022-11-30 17:00:19 +00:00
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
2022-02-26 16:34:43 +00:00
"github.com/ethereum/go-ethereum/crypto"
2022-11-30 17:00:19 +00:00
"github.com/ethereum/go-ethereum/signer/core/apitypes"
2022-06-19 09:43:41 +00:00
"github.com/evmos/ethermint/ethereum/eip712"
"github.com/evmos/ethermint/types"
2020-04-01 18:49:21 +00:00
2022-01-05 07:28:27 +00:00
"github.com/ethereum/go-ethereum/common"
2021-06-01 17:14:33 +00:00
ethtypes "github.com/ethereum/go-ethereum/core/types"
2021-05-31 09:05:32 +00:00
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/tx"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
2022-11-30 17:00:19 +00:00
kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
2021-04-21 13:41:30 +00:00
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
2022-11-30 17:00:19 +00:00
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
2021-12-28 07:59:28 +00:00
"github.com/cosmos/cosmos-sdk/simapp"
2021-04-17 10:00:07 +00:00
"github.com/cosmos/cosmos-sdk/testutil/testdata"
2020-04-01 18:49:21 +00:00
sdk "github.com/cosmos/cosmos-sdk/types"
2022-09-17 13:37:47 +00:00
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
2021-05-31 09:05:32 +00:00
"github.com/cosmos/cosmos-sdk/types/tx/signing"
2022-11-30 17:00:19 +00:00
sdkante "github.com/cosmos/cosmos-sdk/x/auth/ante"
2021-05-31 09:05:32 +00:00
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
2021-04-17 10:00:07 +00:00
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
2022-11-30 17:00:19 +00:00
authz "github.com/cosmos/cosmos-sdk/x/authz"
2022-09-17 13:37:47 +00:00
cryptocodec "github.com/evmos/ethermint/crypto/codec"
2022-11-30 17:00:19 +00:00
"github.com/evmos/ethermint/crypto/ethsecp256k1"
2020-04-01 18:49:21 +00:00
2022-09-17 13:37:47 +00:00
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
evtypes "github.com/cosmos/cosmos-sdk/x/evidence/types"
"github.com/cosmos/cosmos-sdk/x/feegrant"
2022-11-30 17:00:19 +00:00
govtypesv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
2022-06-19 09:43:41 +00:00
"github.com/evmos/ethermint/app"
ante "github.com/evmos/ethermint/app/ante"
"github.com/evmos/ethermint/encoding"
"github.com/evmos/ethermint/tests"
"github.com/evmos/ethermint/x/evm/statedb"
evmtypes "github.com/evmos/ethermint/x/evm/types"
feemarkettypes "github.com/evmos/ethermint/x/feemarket/types"
2020-04-01 18:49:21 +00:00
2021-04-17 10:00:07 +00:00
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
2020-04-01 18:49:21 +00:00
)
type AnteTestSuite struct {
suite . Suite
2021-12-28 07:59:28 +00:00
ctx sdk . Context
app * app . EthermintApp
clientCtx client . Context
anteHandler sdk . AnteHandler
ethSigner ethtypes . Signer
enableFeemarket bool
enableLondonHF bool
2022-05-03 17:51:02 +00:00
evmParamsOption func ( * evmtypes . Params )
2020-04-01 18:49:21 +00:00
}
2022-06-05 09:22:33 +00:00
const TestGasLimit uint64 = 100000
2022-01-05 07:28:27 +00:00
func ( suite * AnteTestSuite ) StateDB ( ) * statedb . StateDB {
return statedb . New ( suite . ctx , suite . app . EvmKeeper , statedb . NewEmptyTxConfig ( common . BytesToHash ( suite . ctx . HeaderHash ( ) . Bytes ( ) ) ) )
}
2020-04-01 18:49:21 +00:00
func ( suite * AnteTestSuite ) SetupTest ( ) {
checkTx := false
2021-10-19 08:49:29 +00:00
2021-12-28 07:59:28 +00:00
suite . app = app . Setup ( checkTx , func ( app * app . EthermintApp , genesis simapp . GenesisState ) simapp . GenesisState {
if suite . enableFeemarket {
// setup feemarketGenesis params
feemarketGenesis := feemarkettypes . DefaultGenesisState ( )
feemarketGenesis . Params . EnableHeight = 1
feemarketGenesis . Params . NoBaseFee = false
// Verify feeMarket genesis
err := feemarketGenesis . Validate ( )
suite . Require ( ) . NoError ( err )
genesis [ feemarkettypes . ModuleName ] = app . AppCodec ( ) . MustMarshalJSON ( feemarketGenesis )
}
2022-05-03 17:51:02 +00:00
evmGenesis := evmtypes . DefaultGenesisState ( )
2022-06-22 10:51:14 +00:00
evmGenesis . Params . AllowUnprotectedTxs = false
2021-12-28 07:59:28 +00:00
if ! suite . enableLondonHF {
2022-07-28 13:43:49 +00:00
maxInt := sdkmath . NewInt ( math . MaxInt64 )
2021-12-28 07:59:28 +00:00
evmGenesis . Params . ChainConfig . LondonBlock = & maxInt
2022-02-14 23:08:41 +00:00
evmGenesis . Params . ChainConfig . ArrowGlacierBlock = & maxInt
2022-07-08 10:58:04 +00:00
evmGenesis . Params . ChainConfig . GrayGlacierBlock = & maxInt
evmGenesis . Params . ChainConfig . MergeNetsplitBlock = & maxInt
2022-11-30 17:00:19 +00:00
evmGenesis . Params . ChainConfig . ShanghaiBlock = & maxInt
evmGenesis . Params . ChainConfig . CancunBlock = & maxInt
2021-12-28 07:59:28 +00:00
}
2022-05-03 17:51:02 +00:00
if suite . evmParamsOption != nil {
suite . evmParamsOption ( & evmGenesis . Params )
}
genesis [ evmtypes . ModuleName ] = app . AppCodec ( ) . MustMarshalJSON ( evmGenesis )
2021-12-28 07:59:28 +00:00
return genesis
} )
2021-10-19 08:49:29 +00:00
2021-08-17 14:11:26 +00:00
suite . ctx = suite . app . BaseApp . NewContext ( checkTx , tmproto . Header { Height : 2 , ChainID : "ethermint_9000-1" , Time : time . Now ( ) . UTC ( ) } )
2021-05-31 09:05:32 +00:00
suite . ctx = suite . ctx . WithMinGasPrices ( sdk . NewDecCoins ( sdk . NewDecCoin ( evmtypes . DefaultEVMDenom , sdk . OneInt ( ) ) ) )
suite . ctx = suite . ctx . WithBlockGasMeter ( sdk . NewGasMeter ( 1000000000000000000 ) )
suite . app . EvmKeeper . WithChainID ( suite . ctx )
2020-04-01 18:49:21 +00:00
2021-05-31 09:05:32 +00:00
infCtx := suite . ctx . WithGasMeter ( sdk . NewInfiniteGasMeter ( ) )
suite . app . AccountKeeper . SetParams ( infCtx , authtypes . DefaultParams ( ) )
2020-09-02 19:41:05 +00:00
2021-06-04 13:45:37 +00:00
encodingConfig := encoding . MakeConfig ( app . ModuleBasics )
2021-04-17 10:00:07 +00:00
// We're using TestMsg amino encoding in some tests, so register it here.
2021-05-31 09:05:32 +00:00
encodingConfig . Amino . RegisterConcrete ( & testdata . TestMsg { } , "testdata.TestMsg" , nil )
2022-11-30 17:00:19 +00:00
eip712 . SetEncodingConfig ( encodingConfig )
2021-05-31 09:05:32 +00:00
suite . clientCtx = client . Context { } . WithTxConfig ( encodingConfig . TxConfig )
2021-04-17 10:00:07 +00:00
2022-07-19 04:50:31 +00:00
anteHandler , err := ante . NewAnteHandler ( ante . HandlerOptions {
2022-03-11 10:31:16 +00:00
AccountKeeper : suite . app . AccountKeeper ,
BankKeeper : suite . app . BankKeeper ,
EvmKeeper : suite . app . EvmKeeper ,
FeegrantKeeper : suite . app . FeeGrantKeeper ,
IBCKeeper : suite . app . IBCKeeper ,
FeeMarketKeeper : suite . app . FeeMarketKeeper ,
SignModeHandler : encodingConfig . TxConfig . SignModeHandler ( ) ,
SigGasConsumer : ante . DefaultSigVerificationGasConsumer ,
2022-07-19 04:50:31 +00:00
} )
suite . Require ( ) . NoError ( err )
2022-01-02 22:44:46 +00:00
2022-07-19 04:50:31 +00:00
suite . anteHandler = anteHandler
2021-06-01 17:14:33 +00:00
suite . ethSigner = ethtypes . LatestSignerForChainID ( suite . app . EvmKeeper . ChainID ( ) )
2020-04-01 18:49:21 +00:00
}
func TestAnteTestSuite ( t * testing . T ) {
2021-12-28 07:59:28 +00:00
suite . Run ( t , & AnteTestSuite {
enableLondonHF : true ,
} )
2020-04-01 18:49:21 +00:00
}
2022-05-31 16:28:46 +00:00
func ( s * AnteTestSuite ) BuildTestEthTx (
from common . Address ,
to common . Address ,
amount * big . Int ,
input [ ] byte ,
gasPrice * big . Int ,
gasFeeCap * big . Int ,
gasTipCap * big . Int ,
accesses * ethtypes . AccessList ,
) * evmtypes . MsgEthereumTx {
chainID := s . app . EvmKeeper . ChainID ( )
nonce := s . app . EvmKeeper . GetNonce (
s . ctx ,
common . BytesToAddress ( from . Bytes ( ) ) ,
)
2022-06-05 09:22:33 +00:00
2022-05-31 16:28:46 +00:00
msgEthereumTx := evmtypes . NewTx (
chainID ,
nonce ,
& to ,
amount ,
2022-06-05 09:22:33 +00:00
TestGasLimit ,
2022-05-31 16:28:46 +00:00
gasPrice ,
gasFeeCap ,
gasTipCap ,
input ,
accesses ,
)
msgEthereumTx . From = from . String ( )
return msgEthereumTx
}
2021-05-31 09:05:32 +00:00
// CreateTestTx is a helper function to create a tx given multiple inputs.
func ( suite * AnteTestSuite ) CreateTestTx (
2021-06-21 10:44:37 +00:00
msg * evmtypes . MsgEthereumTx , priv cryptotypes . PrivKey , accNum uint64 , signCosmosTx bool ,
2021-12-23 16:07:23 +00:00
unsetExtensionOptions ... bool ,
2021-05-31 09:05:32 +00:00
) authsigning . Tx {
2021-06-21 10:44:37 +00:00
return suite . CreateTestTxBuilder ( msg , priv , accNum , signCosmosTx ) . GetTx ( )
2021-06-21 07:59:45 +00:00
}
// CreateTestTxBuilder is a helper function to create a tx builder given multiple inputs.
func ( suite * AnteTestSuite ) CreateTestTxBuilder (
2021-06-21 10:44:37 +00:00
msg * evmtypes . MsgEthereumTx , priv cryptotypes . PrivKey , accNum uint64 , signCosmosTx bool ,
2021-12-23 16:07:23 +00:00
unsetExtensionOptions ... bool ,
2021-06-21 07:59:45 +00:00
) client . TxBuilder {
2021-12-23 16:07:23 +00:00
var option * codectypes . Any
var err error
if len ( unsetExtensionOptions ) == 0 {
option , err = codectypes . NewAnyWithValue ( & evmtypes . ExtensionOptionsEthereumTx { } )
suite . Require ( ) . NoError ( err )
}
2020-04-01 18:49:21 +00:00
2021-06-21 10:44:37 +00:00
txBuilder := suite . clientCtx . TxConfig . NewTxBuilder ( )
builder , ok := txBuilder . ( authtx . ExtensionOptionsTxBuilder )
2021-05-31 09:05:32 +00:00
suite . Require ( ) . True ( ok )
2020-04-01 18:49:21 +00:00
2021-12-23 16:07:23 +00:00
if len ( unsetExtensionOptions ) == 0 {
builder . SetExtensionOptions ( option )
}
2020-04-01 18:49:21 +00:00
2021-06-01 17:14:33 +00:00
err = msg . Sign ( suite . ethSigner , tests . NewSigner ( priv ) )
2021-05-31 09:05:32 +00:00
suite . Require ( ) . NoError ( err )
2020-04-01 18:49:21 +00:00
2022-07-19 15:12:48 +00:00
msg . From = ""
2021-05-31 09:05:32 +00:00
err = builder . SetMsgs ( msg )
2021-06-15 17:39:41 +00:00
suite . Require ( ) . NoError ( err )
2021-07-05 16:39:08 +00:00
txData , err := evmtypes . UnpackTxData ( msg . Data )
suite . Require ( ) . NoError ( err )
2022-07-28 13:43:49 +00:00
fees := sdk . NewCoins ( sdk . NewCoin ( evmtypes . DefaultEVMDenom , sdkmath . NewIntFromBigInt ( txData . Fee ( ) ) ) )
2021-05-31 09:05:32 +00:00
builder . SetFeeAmount ( fees )
builder . SetGasLimit ( msg . GetGas ( ) )
2020-04-01 18:49:21 +00:00
2021-06-21 10:44:37 +00:00
if signCosmosTx {
// First round: we gather all the signer infos. We use the "set empty
// signature" hack to do that.
sigV2 := signing . SignatureV2 {
PubKey : priv . PubKey ( ) ,
Data : & signing . SingleSignatureData {
SignMode : suite . clientCtx . TxConfig . SignModeHandler ( ) . DefaultMode ( ) ,
Signature : nil ,
} ,
2021-07-05 16:39:08 +00:00
Sequence : txData . GetNonce ( ) ,
2021-06-21 10:44:37 +00:00
}
sigsV2 := [ ] signing . SignatureV2 { sigV2 }
err = txBuilder . SetSignatures ( sigsV2 ... )
suite . Require ( ) . NoError ( err )
// Second round: all signer infos are set, so each signer can sign.
signerData := authsigning . SignerData {
ChainID : suite . ctx . ChainID ( ) ,
AccountNumber : accNum ,
2021-07-05 16:39:08 +00:00
Sequence : txData . GetNonce ( ) ,
2021-06-21 10:44:37 +00:00
}
sigV2 , err = tx . SignWithPrivKey (
suite . clientCtx . TxConfig . SignModeHandler ( ) . DefaultMode ( ) , signerData ,
2021-07-05 16:39:08 +00:00
txBuilder , priv , suite . clientCtx . TxConfig , txData . GetNonce ( ) ,
2021-06-21 10:44:37 +00:00
)
suite . Require ( ) . NoError ( err )
sigsV2 = [ ] signing . SignatureV2 { sigV2 }
err = txBuilder . SetSignatures ( sigsV2 ... )
suite . Require ( ) . NoError ( err )
2021-05-31 09:05:32 +00:00
}
2021-06-21 10:44:37 +00:00
return txBuilder
2021-05-31 09:05:32 +00:00
}
2021-05-12 13:08:31 +00:00
2022-07-28 13:43:49 +00:00
func ( suite * AnteTestSuite ) CreateTestCosmosTxBuilder ( gasPrice sdkmath . Int , denom string , msgs ... sdk . Msg ) client . TxBuilder {
2022-05-31 16:28:46 +00:00
txBuilder := suite . clientCtx . TxConfig . NewTxBuilder ( )
2022-06-05 09:22:33 +00:00
txBuilder . SetGasLimit ( TestGasLimit )
fees := & sdk . Coins { { Denom : denom , Amount : gasPrice . MulRaw ( int64 ( TestGasLimit ) ) } }
2022-05-31 16:28:46 +00:00
txBuilder . SetFeeAmount ( * fees )
err := txBuilder . SetMsgs ( msgs ... )
suite . Require ( ) . NoError ( err )
return txBuilder
}
2022-02-26 16:34:43 +00:00
func ( suite * AnteTestSuite ) CreateTestEIP712TxBuilderMsgSend ( from sdk . AccAddress , priv cryptotypes . PrivKey , chainId string , gas uint64 , gasAmount sdk . Coins ) client . TxBuilder {
// Build MsgSend
recipient := sdk . AccAddress ( common . Address { } . Bytes ( ) )
2022-11-30 17:00:19 +00:00
msgSend := banktypes . NewMsgSend ( from , recipient , sdk . NewCoins ( sdk . NewCoin ( evmtypes . DefaultEVMDenom , sdkmath . NewInt ( 1 ) ) ) )
return suite . CreateTestEIP712SingleMessageTxBuilder ( from , priv , chainId , gas , gasAmount , msgSend )
2022-02-26 16:34:43 +00:00
}
func ( suite * AnteTestSuite ) CreateTestEIP712TxBuilderMsgDelegate ( from sdk . AccAddress , priv cryptotypes . PrivKey , chainId string , gas uint64 , gasAmount sdk . Coins ) client . TxBuilder {
// Build MsgSend
valEthAddr := tests . GenerateAddress ( )
valAddr := sdk . ValAddress ( valEthAddr . Bytes ( ) )
2022-11-30 17:00:19 +00:00
msgSend := stakingtypes . NewMsgDelegate ( from , valAddr , sdk . NewCoin ( evmtypes . DefaultEVMDenom , sdkmath . NewInt ( 20 ) ) )
return suite . CreateTestEIP712SingleMessageTxBuilder ( from , priv , chainId , gas , gasAmount , msgSend )
2022-02-26 16:34:43 +00:00
}
2022-09-17 13:37:47 +00:00
func ( suite * AnteTestSuite ) CreateTestEIP712MsgCreateValidator ( from sdk . AccAddress , priv cryptotypes . PrivKey , chainId string , gas uint64 , gasAmount sdk . Coins ) client . TxBuilder {
// Build MsgCreateValidator
valAddr := sdk . ValAddress ( from . Bytes ( ) )
privEd := ed25519 . GenPrivKey ( )
2022-11-30 17:00:19 +00:00
msgCreate , err := stakingtypes . NewMsgCreateValidator (
2022-09-17 13:37:47 +00:00
valAddr ,
privEd . PubKey ( ) ,
sdk . NewCoin ( evmtypes . DefaultEVMDenom , sdk . NewInt ( 20 ) ) ,
2022-11-30 17:00:19 +00:00
stakingtypes . NewDescription ( "moniker" , "indentity" , "website" , "security_contract" , "details" ) ,
stakingtypes . NewCommissionRates ( sdk . OneDec ( ) , sdk . OneDec ( ) , sdk . OneDec ( ) ) ,
2022-09-17 13:37:47 +00:00
sdk . OneInt ( ) ,
)
suite . Require ( ) . NoError ( err )
2022-11-30 17:00:19 +00:00
return suite . CreateTestEIP712SingleMessageTxBuilder ( from , priv , chainId , gas , gasAmount , msgCreate )
}
func ( suite * AnteTestSuite ) CreateTestEIP712MsgCreateValidator2 ( from sdk . AccAddress , priv cryptotypes . PrivKey , chainId string , gas uint64 , gasAmount sdk . Coins ) client . TxBuilder {
// Build MsgCreateValidator
valAddr := sdk . ValAddress ( from . Bytes ( ) )
privEd := ed25519 . GenPrivKey ( )
msgCreate , err := stakingtypes . NewMsgCreateValidator (
valAddr ,
privEd . PubKey ( ) ,
sdk . NewCoin ( evmtypes . DefaultEVMDenom , sdk . NewInt ( 20 ) ) ,
// Ensure optional fields can be left blank
stakingtypes . NewDescription ( "moniker" , "indentity" , "" , "" , "" ) ,
stakingtypes . NewCommissionRates ( sdk . OneDec ( ) , sdk . OneDec ( ) , sdk . OneDec ( ) ) ,
sdk . OneInt ( ) ,
)
suite . Require ( ) . NoError ( err )
return suite . CreateTestEIP712SingleMessageTxBuilder ( from , priv , chainId , gas , gasAmount , msgCreate )
2022-09-17 13:37:47 +00:00
}
func ( suite * AnteTestSuite ) CreateTestEIP712SubmitProposal ( from sdk . AccAddress , priv cryptotypes . PrivKey , chainId string , gas uint64 , gasAmount sdk . Coins , deposit sdk . Coins ) client . TxBuilder {
2022-11-30 17:00:19 +00:00
proposal , ok := govtypes . ContentFromProposalType ( "My proposal" , "My description" , govtypes . ProposalTypeText )
2022-09-17 13:37:47 +00:00
suite . Require ( ) . True ( ok )
2022-11-30 17:00:19 +00:00
msgSubmit , err := govtypes . NewMsgSubmitProposal ( proposal , deposit , from )
2022-09-17 13:37:47 +00:00
suite . Require ( ) . NoError ( err )
2022-11-30 17:00:19 +00:00
return suite . CreateTestEIP712SingleMessageTxBuilder ( from , priv , chainId , gas , gasAmount , msgSubmit )
2022-09-17 13:37:47 +00:00
}
func ( suite * AnteTestSuite ) CreateTestEIP712GrantAllowance ( from sdk . AccAddress , priv cryptotypes . PrivKey , chainId string , gas uint64 , gasAmount sdk . Coins ) client . TxBuilder {
spendLimit := sdk . NewCoins ( sdk . NewInt64Coin ( evmtypes . DefaultEVMDenom , 10 ) )
threeHours := time . Now ( ) . Add ( 3 * time . Hour )
basic := & feegrant . BasicAllowance {
SpendLimit : spendLimit ,
Expiration : & threeHours ,
}
granted := tests . GenerateAddress ( )
grantedAddr := suite . app . AccountKeeper . NewAccountWithAddress ( suite . ctx , granted . Bytes ( ) )
msgGrant , err := feegrant . NewMsgGrantAllowance ( basic , from , grantedAddr . GetAddress ( ) )
suite . Require ( ) . NoError ( err )
2022-11-30 17:00:19 +00:00
return suite . CreateTestEIP712SingleMessageTxBuilder ( from , priv , chainId , gas , gasAmount , msgGrant )
2022-09-17 13:37:47 +00:00
}
func ( suite * AnteTestSuite ) CreateTestEIP712MsgEditValidator ( from sdk . AccAddress , priv cryptotypes . PrivKey , chainId string , gas uint64 , gasAmount sdk . Coins ) client . TxBuilder {
valAddr := sdk . ValAddress ( from . Bytes ( ) )
2022-11-30 17:00:19 +00:00
msgEdit := stakingtypes . NewMsgEditValidator (
2022-09-17 13:37:47 +00:00
valAddr ,
2022-11-30 17:00:19 +00:00
stakingtypes . NewDescription ( "moniker" , "identity" , "website" , "security_contract" , "details" ) ,
2022-09-17 13:37:47 +00:00
nil ,
nil ,
)
2022-11-30 17:00:19 +00:00
return suite . CreateTestEIP712SingleMessageTxBuilder ( from , priv , chainId , gas , gasAmount , msgEdit )
2022-09-17 13:37:47 +00:00
}
func ( suite * AnteTestSuite ) CreateTestEIP712MsgSubmitEvidence ( from sdk . AccAddress , priv cryptotypes . PrivKey , chainId string , gas uint64 , gasAmount sdk . Coins ) client . TxBuilder {
pk := ed25519 . GenPrivKey ( )
msgEvidence , err := evtypes . NewMsgSubmitEvidence ( from , & evtypes . Equivocation {
Height : 11 ,
Time : time . Now ( ) . UTC ( ) ,
Power : 100 ,
ConsensusAddress : pk . PubKey ( ) . Address ( ) . String ( ) ,
} )
suite . Require ( ) . NoError ( err )
2022-11-30 17:00:19 +00:00
return suite . CreateTestEIP712SingleMessageTxBuilder ( from , priv , chainId , gas , gasAmount , msgEvidence )
}
func ( suite * AnteTestSuite ) CreateTestEIP712MsgVoteV1 ( from sdk . AccAddress , priv cryptotypes . PrivKey , chainId string , gas uint64 , gasAmount sdk . Coins ) client . TxBuilder {
msgVote := govtypesv1 . NewMsgVote ( from , 1 , govtypesv1 . VoteOption_VOTE_OPTION_YES , "" )
return suite . CreateTestEIP712SingleMessageTxBuilder ( from , priv , chainId , gas , gasAmount , msgVote )
}
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 := govtypes . ContentFromProposalType ( "My proposal 1" , "My description 1" , govtypes . ProposalTypeText )
suite . Require ( ) . True ( ok )
content1 , err := govtypesv1 . NewLegacyContent (
proposal1 ,
sdk . MustBech32ifyAddressBytes ( sdk . GetConfig ( ) . GetBech32AccountAddrPrefix ( ) , authAcc . GetAddress ( ) . Bytes ( ) ) ,
)
suite . Require ( ) . NoError ( err )
proposal2 , ok := govtypes . ContentFromProposalType ( "My proposal 2" , "My description 2" , govtypes . ProposalTypeText )
suite . Require ( ) . True ( ok )
content2 , err := govtypesv1 . NewLegacyContent (
proposal2 ,
sdk . MustBech32ifyAddressBytes ( sdk . GetConfig ( ) . GetBech32AccountAddrPrefix ( ) , authAcc . GetAddress ( ) . Bytes ( ) ) ,
)
suite . Require ( ) . NoError ( err )
proposalMsgs := [ ] sdk . Msg {
content1 ,
content2 ,
}
// Build V1 proposal
msgProposal , err := govtypesv1 . 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 . CreateTestEIP712SingleMessageTxBuilder ( 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 := banktypes . NewMsgSend ( from , recipient , sdk . NewCoins ( sdk . NewCoin ( evmtypes . DefaultEVMDenom , sdkmath . NewInt ( 1 ) ) ) )
msgExec := authz . NewMsgExec ( from , [ ] sdk . Msg { msgSend } )
return suite . CreateTestEIP712SingleMessageTxBuilder ( from , priv , chainId , gas , gasAmount , & msgExec )
}
func ( suite * AnteTestSuite ) CreateTestEIP712MultipleMsgSend ( from sdk . AccAddress , priv cryptotypes . PrivKey , chainId string , gas uint64 , gasAmount sdk . Coins ) client . TxBuilder {
recipient := sdk . AccAddress ( common . Address { } . Bytes ( ) )
msgSend := banktypes . NewMsgSend ( from , recipient , sdk . NewCoins ( sdk . NewCoin ( evmtypes . DefaultEVMDenom , sdkmath . NewInt ( 1 ) ) ) )
return suite . CreateTestEIP712CosmosTxBuilder ( from , priv , chainId , gas , gasAmount , [ ] sdk . Msg { msgSend , msgSend , msgSend } )
}
// Fails
func ( suite * AnteTestSuite ) CreateTestEIP712MultipleSignerMsgs ( from sdk . AccAddress , priv cryptotypes . PrivKey , chainId string , gas uint64 , gasAmount sdk . Coins ) client . TxBuilder {
recipient := sdk . AccAddress ( common . Address { } . Bytes ( ) )
msgSend1 := banktypes . NewMsgSend ( from , recipient , sdk . NewCoins ( sdk . NewCoin ( evmtypes . DefaultEVMDenom , sdkmath . NewInt ( 1 ) ) ) )
msgSend2 := banktypes . NewMsgSend ( recipient , from , sdk . NewCoins ( sdk . NewCoin ( evmtypes . DefaultEVMDenom , sdkmath . NewInt ( 1 ) ) ) )
return suite . CreateTestEIP712CosmosTxBuilder ( from , priv , chainId , gas , gasAmount , [ ] sdk . Msg { msgSend1 , msgSend2 } )
2022-09-17 13:37:47 +00:00
}
// 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 {
msgsBytes := make ( [ ] json . RawMessage , 0 , len ( msgs ) )
for _ , msg := range msgs {
legacyMsg , ok := msg . ( legacytx . LegacyMsg )
if ! ok {
panic ( fmt . Errorf ( "expected %T when using amino JSON" , ( * legacytx . LegacyMsg ) ( nil ) ) )
}
msgsBytes = append ( msgsBytes , json . RawMessage ( legacyMsg . GetSignBytes ( ) ) )
}
var stdTip * legacytx . StdTip
if tip != nil {
if tip . Tipper == "" {
panic ( fmt . Errorf ( "tipper cannot be empty" ) )
}
stdTip = & legacytx . StdTip { Amount : tip . Amount , Tipper : tip . Tipper }
}
bz , err := cdc . MarshalJSON ( legacytx . StdSignDoc {
AccountNumber : accnum ,
ChainID : chainID ,
Fee : json . RawMessage ( fee . Bytes ( ) ) ,
Memo : memo ,
Msgs : msgsBytes ,
Sequence : sequence ,
TimeoutHeight : timeout ,
Tip : stdTip ,
} )
if err != nil {
panic ( err )
}
return sdk . MustSortJSON ( bz )
}
2022-11-30 17:00:19 +00:00
func ( suite * AnteTestSuite ) CreateTestEIP712SingleMessageTxBuilder (
2022-02-26 16:34:43 +00:00
from sdk . AccAddress , priv cryptotypes . PrivKey , chainId string , gas uint64 , gasAmount sdk . Coins , msg sdk . Msg ,
2022-11-30 17:00:19 +00:00
) client . TxBuilder {
return suite . CreateTestEIP712CosmosTxBuilder ( from , priv , chainId , gas , gasAmount , [ ] sdk . Msg { msg } )
}
func ( suite * AnteTestSuite ) CreateTestEIP712CosmosTxBuilder (
from sdk . AccAddress , priv cryptotypes . PrivKey , chainId string , gas uint64 , gasAmount sdk . Coins , msgs [ ] sdk . Msg ,
2022-02-26 16:34:43 +00:00
) client . TxBuilder {
var err error
nonce , err := suite . app . AccountKeeper . GetSequence ( suite . ctx , from )
suite . Require ( ) . NoError ( err )
pc , err := types . ParseChainID ( chainId )
suite . Require ( ) . NoError ( err )
ethChainId := pc . Uint64 ( )
// GenerateTypedData TypedData
var ethermintCodec codec . ProtoCodecMarshaler
2022-09-17 13:37:47 +00:00
registry := codectypes . NewInterfaceRegistry ( )
types . RegisterInterfaces ( registry )
ethermintCodec = codec . NewProtoCodec ( registry )
cryptocodec . RegisterInterfaces ( registry )
2022-02-26 16:34:43 +00:00
fee := legacytx . NewStdFee ( gas , gasAmount )
accNumber := suite . app . AccountKeeper . GetAccount ( suite . ctx , from ) . GetAccountNumber ( )
2022-11-30 17:00:19 +00:00
data := legacytx . StdSignBytes ( chainId , accNumber , nonce , 0 , fee , msgs , "" , nil )
typedData , err := eip712 . WrapTxToTypedData ( ethermintCodec , ethChainId , msgs [ 0 ] , data , & eip712 . FeeDelegationOptions {
2022-02-26 16:34:43 +00:00
FeePayer : from ,
} )
suite . Require ( ) . NoError ( err )
2022-11-30 17:00:19 +00:00
sigHash , _ , err := apitypes . TypedDataAndHash ( typedData )
2022-02-26 16:34:43 +00:00
suite . Require ( ) . NoError ( err )
// Sign typedData
keyringSigner := tests . NewSigner ( priv )
signature , pubKey , err := keyringSigner . SignByAddress ( from , sigHash )
suite . Require ( ) . NoError ( err )
signature [ crypto . RecoveryIDOffset ] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper
// Add ExtensionOptionsWeb3Tx extension
var option * codectypes . Any
option , err = codectypes . NewAnyWithValue ( & types . ExtensionOptionsWeb3Tx {
FeePayer : from . String ( ) ,
TypedDataChainID : ethChainId ,
FeePayerSig : signature ,
} )
suite . Require ( ) . NoError ( err )
suite . clientCtx . TxConfig . SignModeHandler ( )
txBuilder := suite . clientCtx . TxConfig . NewTxBuilder ( )
builder , ok := txBuilder . ( authtx . ExtensionOptionsTxBuilder )
suite . Require ( ) . True ( ok )
builder . SetExtensionOptions ( option )
builder . SetFeeAmount ( gasAmount )
builder . SetGasLimit ( gas )
sigsV2 := signing . SignatureV2 {
PubKey : pubKey ,
Data : & signing . SingleSignatureData {
SignMode : signing . SignMode_SIGN_MODE_LEGACY_AMINO_JSON ,
} ,
Sequence : nonce ,
}
err = builder . SetSignatures ( sigsV2 )
suite . Require ( ) . NoError ( err )
2022-11-30 17:00:19 +00:00
err = builder . SetMsgs ( msgs ... )
2022-02-26 16:34:43 +00:00
suite . Require ( ) . NoError ( err )
return builder
}
2022-11-30 17:00:19 +00:00
// Generate a set of pub/priv keys to be used in creating multi-keys
func ( suite * AnteTestSuite ) GenerateMultipleKeys ( n int ) ( [ ] cryptotypes . PrivKey , [ ] cryptotypes . PubKey ) {
privKeys := make ( [ ] cryptotypes . PrivKey , n )
pubKeys := make ( [ ] cryptotypes . PubKey , n )
for i := 0 ; i < n ; i ++ {
privKey , err := ethsecp256k1 . GenerateKey ( )
suite . Require ( ) . NoError ( err )
privKeys [ i ] = privKey
pubKeys [ i ] = privKey . PubKey ( )
}
return privKeys , pubKeys
}
// generateSingleSignature signs the given sign doc bytes using the given signType (EIP-712 or Standard)
func ( suite * AnteTestSuite ) generateSingleSignature ( signMode signing . SignMode , privKey cryptotypes . PrivKey , signDocBytes [ ] byte , signType string ) ( signature signing . SignatureV2 ) {
var (
msg [ ] byte
err error
)
msg = signDocBytes
if signType == "EIP-712" {
msg , err = eip712 . GetEIP712HashForMsg ( signDocBytes )
suite . Require ( ) . NoError ( err )
}
sigBytes , _ := privKey . Sign ( msg )
sigData := & signing . SingleSignatureData {
SignMode : signMode ,
Signature : sigBytes ,
}
return signing . SignatureV2 {
PubKey : privKey . PubKey ( ) ,
Data : sigData ,
}
}
// generateMultikeySignatures signs a set of messages using each private key within a given multi-key
func ( suite * AnteTestSuite ) generateMultikeySignatures ( signMode signing . SignMode , privKeys [ ] cryptotypes . PrivKey , signDocBytes [ ] byte , signType string ) ( signatures [ ] signing . SignatureV2 ) {
n := len ( privKeys )
signatures = make ( [ ] signing . SignatureV2 , n )
for i := 0 ; i < n ; i ++ {
privKey := privKeys [ i ]
currentType := signType
// If mixed type, alternate signing type on each iteration
if signType == "mixed" {
if i % 2 == 0 {
currentType = "EIP-712"
} else {
currentType = "Standard"
}
}
signatures [ i ] = suite . generateSingleSignature (
signMode ,
privKey ,
signDocBytes ,
currentType ,
)
}
return signatures
}
// RegisterAccount creates an account with the keeper and populates the initial balance
func ( suite * AnteTestSuite ) RegisterAccount ( pubKey cryptotypes . PubKey , balance * big . Int ) {
acc := suite . app . AccountKeeper . NewAccountWithAddress ( suite . ctx , sdk . AccAddress ( pubKey . Address ( ) ) )
suite . app . AccountKeeper . SetAccount ( suite . ctx , acc )
suite . app . EvmKeeper . SetBalance ( suite . ctx , common . BytesToAddress ( pubKey . Address ( ) ) , balance )
}
// createSignerBytes generates sign doc bytes using the given parameters
func ( suite * AnteTestSuite ) createSignerBytes ( chainId string , signMode signing . SignMode , pubKey cryptotypes . PubKey , txBuilder client . TxBuilder ) [ ] byte {
acc , err := sdkante . GetSignerAcc ( suite . ctx , suite . app . AccountKeeper , sdk . AccAddress ( pubKey . Address ( ) ) )
suite . Require ( ) . NoError ( err )
signerInfo := authsigning . SignerData {
Address : sdk . MustBech32ifyAddressBytes ( sdk . GetConfig ( ) . GetBech32AccountAddrPrefix ( ) , acc . GetAddress ( ) . Bytes ( ) ) ,
ChainID : chainId ,
AccountNumber : acc . GetAccountNumber ( ) ,
Sequence : acc . GetSequence ( ) ,
PubKey : pubKey ,
}
signerBytes , err := suite . clientCtx . TxConfig . SignModeHandler ( ) . GetSignBytes (
signMode ,
signerInfo ,
txBuilder . GetTx ( ) ,
)
suite . Require ( ) . NoError ( err )
return signerBytes
}
// createBaseTxBuilder creates a TxBuilder to be used for Single- or Multi-signing
func ( suite * AnteTestSuite ) createBaseTxBuilder ( msg sdk . Msg , gas uint64 ) client . TxBuilder {
txBuilder := suite . clientCtx . TxConfig . NewTxBuilder ( )
txBuilder . SetGasLimit ( gas )
txBuilder . SetFeeAmount ( sdk . NewCoins (
sdk . NewCoin ( "aphoton" , sdk . NewInt ( 10000 ) ) ,
) )
err := txBuilder . SetMsgs ( msg )
suite . Require ( ) . NoError ( err )
txBuilder . SetMemo ( "" )
return txBuilder
}
// CreateTestSignedMultisigTx creates and sign a multi-signed tx for the given message. `signType` indicates whether to use standard signing ("Standard"),
// EIP-712 signing ("EIP-712"), or a mix of the two ("mixed").
func ( suite * AnteTestSuite ) CreateTestSignedMultisigTx ( privKeys [ ] cryptotypes . PrivKey , signMode signing . SignMode , msg sdk . Msg , chainId string , gas uint64 , signType string ) client . TxBuilder {
pubKeys := make ( [ ] cryptotypes . PubKey , len ( privKeys ) )
for i , privKey := range privKeys {
pubKeys [ i ] = privKey . PubKey ( )
}
// Re-derive multikey
numKeys := len ( privKeys )
multiKey := kmultisig . NewLegacyAminoPubKey ( numKeys , pubKeys )
suite . RegisterAccount ( multiKey , big . NewInt ( 10000000000 ) )
txBuilder := suite . createBaseTxBuilder ( msg , gas )
// Prepare signature field
sig := multisig . NewMultisig ( len ( pubKeys ) )
txBuilder . SetSignatures ( signing . SignatureV2 {
PubKey : multiKey ,
Data : sig ,
} )
signerBytes := suite . createSignerBytes ( chainId , signMode , multiKey , txBuilder )
// Sign for each key and update signature field
sigs := suite . generateMultikeySignatures ( signMode , privKeys , signerBytes , signType )
for _ , pkSig := range sigs {
err := multisig . AddSignatureV2 ( sig , pkSig , pubKeys )
suite . Require ( ) . NoError ( err )
}
txBuilder . SetSignatures ( signing . SignatureV2 {
PubKey : multiKey ,
Data : sig ,
} )
return txBuilder
}
func ( suite * AnteTestSuite ) CreateTestSingleSignedTx ( privKey cryptotypes . PrivKey , signMode signing . SignMode , msg sdk . Msg , chainId string , gas uint64 , signType string ) client . TxBuilder {
pubKey := privKey . PubKey ( )
suite . RegisterAccount ( pubKey , big . NewInt ( 10000000000 ) )
txBuilder := suite . createBaseTxBuilder ( msg , gas )
// Prepare signature field
sig := signing . SingleSignatureData { }
txBuilder . SetSignatures ( signing . SignatureV2 {
PubKey : pubKey ,
Data : & sig ,
} )
signerBytes := suite . createSignerBytes ( chainId , signMode , pubKey , txBuilder )
sigData := suite . generateSingleSignature ( signMode , privKey , signerBytes , signType )
txBuilder . SetSignatures ( sigData )
return txBuilder
}
2022-06-05 09:22:33 +00:00
func NextFn ( ctx sdk . Context , _ sdk . Tx , _ bool ) ( sdk . Context , error ) {
return ctx , nil
}
2021-05-31 09:05:32 +00:00
var _ sdk . Tx = & invalidTx { }
type invalidTx struct { }
func ( invalidTx ) GetMsgs ( ) [ ] sdk . Msg { return [ ] sdk . Msg { nil } }
func ( invalidTx ) ValidateBasic ( ) error { return nil }