laconicd/app/middleware/eth_test.go
2022-04-28 23:04:20 +05:30

520 lines
13 KiB
Go

package middleware_test
import (
"math/big"
sdk "github.com/cosmos/cosmos-sdk/types"
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
"github.com/cosmos/cosmos-sdk/x/auth/middleware"
ante "github.com/tharsis/ethermint/app/middleware"
"github.com/tharsis/ethermint/server/config"
"github.com/tharsis/ethermint/tests"
"github.com/tharsis/ethermint/x/evm/statedb"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
ethtypes "github.com/ethereum/go-ethereum/core/types"
)
func nextFn(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) {
return ctx, nil
}
func (suite MiddlewareTestSuite) TestEthSigVerificationDecorator() {
txHandler := middleware.ComposeMiddlewares(noopTxHandler, ante.NewEthSigVerificationMiddleware(suite.app.EvmKeeper))
addr, privKey := tests.NewAddrKey()
signedTx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
signedTx.From = addr.Hex()
err := signedTx.Sign(suite.ethSigner, tests.NewSigner(privKey))
suite.Require().NoError(err)
testCases := []struct {
name string
tx sdk.Tx
reCheckTx bool
expPass bool
}{
{"ReCheckTx", &invalidTx{}, true, false},
{"invalid transaction type", &invalidTx{}, false, false},
{
"invalid sender",
evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 1, &addr, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil),
false,
false,
},
{"successful signature verification", signedTx, false, true},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
_, _, err := txHandler.CheckTx(sdk.WrapSDKContext(suite.ctx), txtypes.Request{Tx: tc.tx}, txtypes.RequestCheckTx{})
if tc.expPass {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite MiddlewareTestSuite) TestNewEthAccountVerificationDecorator() {
txHandler := middleware.ComposeMiddlewares(noopTxHandler, ante.NewEthAccountVerificationMiddleware(
suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.EvmKeeper,
))
addr := tests.GenerateAddress()
tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
tx.From = addr.Hex()
var vmdb *statedb.StateDB
testCases := []struct {
name string
tx sdk.Tx
malleate func()
checkTx bool
expPass bool
}{
{"not CheckTx", nil, func() {}, false, true},
{"invalid transaction type", &invalidTx{}, func() {}, true, false},
{
"sender not set to msg",
evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil),
func() {},
true,
false,
},
{
"sender not EOA",
tx,
func() {
// set not as an EOA
vmdb.SetCode(addr, []byte("1"))
},
true,
false,
},
{
"not enough balance to cover tx cost",
tx,
func() {
// reset back to EOA
vmdb.SetCode(addr, nil)
},
true,
false,
},
{
"success new account",
tx,
func() {
vmdb.AddBalance(addr, big.NewInt(1000000))
},
true,
true,
},
{
"success existing account",
tx,
func() {
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr.Bytes())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
vmdb.AddBalance(addr, big.NewInt(1000000))
},
true,
true,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
vmdb = suite.StateDB()
tc.malleate()
suite.Require().NoError(vmdb.Commit())
_, _, err := txHandler.CheckTx(sdk.WrapSDKContext(suite.ctx.WithIsCheckTx(tc.checkTx)), txtypes.Request{Tx: tc.tx}, txtypes.RequestCheckTx{})
if tc.expPass {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite MiddlewareTestSuite) TestEthNonceVerificationDecorator() {
suite.SetupTest()
txHandler := middleware.ComposeMiddlewares(noopTxHandler, ante.NewEthIncrementSenderSequenceMiddleware(suite.app.AccountKeeper))
addr := tests.GenerateAddress()
tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
tx.From = addr.Hex()
testCases := []struct {
name string
tx sdk.Tx
malleate func()
reCheckTx bool
expPass bool
}{
{"ReCheckTx", &invalidTx{}, func() {}, true, false},
{"invalid transaction type", &invalidTx{}, func() {}, false, false},
{"sender account not found", tx, func() {}, false, false},
{
"sender nonce missmatch",
tx,
func() {
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr.Bytes())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
},
false,
false,
},
{
"success",
tx,
func() {
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr.Bytes())
suite.Require().NoError(acc.SetSequence(1))
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
},
false,
true,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
tc.malleate()
_, _, err := txHandler.CheckTx(sdk.WrapSDKContext(suite.ctx), txtypes.Request{Tx: tc.tx}, txtypes.RequestCheckTx{})
if tc.expPass {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite MiddlewareTestSuite) TestEthGasConsumeDecorator() {
txHandler := middleware.ComposeMiddlewares(noopTxHandler, ante.NewEthGasConsumeMiddleware(suite.app.EvmKeeper, config.DefaultMaxTxGasWanted))
addr := tests.GenerateAddress()
txGasLimit := uint64(1000)
tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), txGasLimit, big.NewInt(1), nil, nil, nil, nil)
tx.From = addr.Hex()
tx2GasLimit := uint64(1000000)
tx2 := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), tx2GasLimit, big.NewInt(1), nil, nil, nil, &ethtypes.AccessList{{Address: addr, StorageKeys: nil}})
tx2.From = addr.Hex()
var vmdb *statedb.StateDB
testCases := []struct {
name string
tx sdk.Tx
gasLimit uint64
malleate func()
expPass bool
expPanic bool
}{
{"invalid transaction type", &invalidTx{}, 0, func() {}, false, false},
{
"sender not found",
evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil),
0,
func() {},
false, false,
},
{
"gas limit too low",
tx,
0,
func() {},
false, false,
},
{
"not enough balance for fees",
tx2,
0,
func() {},
false, false,
},
{
"not enough tx gas",
tx2,
0,
func() {
vmdb.AddBalance(addr, big.NewInt(1000000))
},
false, true,
},
{
"not enough block gas",
tx2,
0,
func() {
vmdb.AddBalance(addr, big.NewInt(1000000))
suite.ctx = suite.ctx.WithBlockGasMeter(sdk.NewGasMeter(1))
},
false, true,
},
{
"success",
tx2,
config.DefaultMaxTxGasWanted, // it's capped
func() {
vmdb.AddBalance(addr, big.NewInt(1000000))
suite.ctx = suite.ctx.WithBlockGasMeter(sdk.NewGasMeter(10000000000000000000))
},
true, false,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
vmdb = suite.StateDB()
tc.malleate()
suite.Require().NoError(vmdb.Commit())
if tc.expPanic {
suite.Require().Panics(func() {
_, _, _ = txHandler.CheckTx(sdk.WrapSDKContext(suite.ctx.WithIsCheckTx(true).WithGasMeter(sdk.NewGasMeter(1))), txtypes.Request{Tx: tc.tx}, txtypes.RequestCheckTx{})
})
return
}
_, _, err := txHandler.CheckTx(sdk.WrapSDKContext(suite.ctx.WithIsCheckTx(true).WithGasMeter(sdk.NewInfiniteGasMeter())), txtypes.Request{Tx: tc.tx}, txtypes.RequestCheckTx{})
// ctx, err := t.AnteHandle(suite.ctx.WithIsCheckTx(true).WithGasMeter(sdk.NewInfiniteGasMeter()), tc.tx, false, nextFn)
if tc.expPass {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
// suite.Require().Equal(tc.gasLimit, ctx.GasMeter().Limit())
})
}
}
func (suite MiddlewareTestSuite) TestCanTransferDecorator() {
// dec := ante.NewCanTransferMiddleware(suite.app.EvmKeeper)
txHandler := middleware.ComposeMiddlewares(noopTxHandler, ante.NewCanTransferMiddleware(suite.app.EvmKeeper))
addr, privKey := tests.NewAddrKey()
suite.app.FeeMarketKeeper.SetBaseFee(suite.ctx, big.NewInt(100))
tx := evmtypes.NewTxContract(
suite.app.EvmKeeper.ChainID(),
1,
big.NewInt(10),
1000,
big.NewInt(150),
big.NewInt(200),
nil,
nil,
&ethtypes.AccessList{},
)
tx2 := evmtypes.NewTxContract(
suite.app.EvmKeeper.ChainID(),
1,
big.NewInt(10),
1000,
big.NewInt(150),
big.NewInt(200),
nil,
nil,
&ethtypes.AccessList{},
)
tx.From = addr.Hex()
err := tx.Sign(suite.ethSigner, tests.NewSigner(privKey))
suite.Require().NoError(err)
var vmdb *statedb.StateDB
testCases := []struct {
name string
tx sdk.Tx
malleate func()
expPass bool
}{
{"invalid transaction type", &invalidTx{}, func() {}, false},
{"AsMessage failed", tx2, func() {}, false},
{
"evm CanTransfer failed",
tx,
func() {
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr.Bytes())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
},
false,
},
{
"success",
tx,
func() {
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr.Bytes())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
vmdb.AddBalance(addr, big.NewInt(1000000))
},
true,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
vmdb = suite.StateDB()
tc.malleate()
suite.Require().NoError(vmdb.Commit())
_, _, err := txHandler.CheckTx(sdk.WrapSDKContext(suite.ctx.WithIsCheckTx(true)), txtypes.Request{Tx: tc.tx}, txtypes.RequestCheckTx{})
if tc.expPass {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite MiddlewareTestSuite) TestEthIncrementSenderSequenceDecorator() {
txHandler := middleware.ComposeMiddlewares(noopTxHandler, ante.NewEthIncrementSenderSequenceMiddleware(suite.app.AccountKeeper))
addr, privKey := tests.NewAddrKey()
contract := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 0, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
contract.From = addr.Hex()
err := contract.Sign(suite.ethSigner, tests.NewSigner(privKey))
suite.Require().NoError(err)
to := tests.GenerateAddress()
tx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 0, &to, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
tx.From = addr.Hex()
err = tx.Sign(suite.ethSigner, tests.NewSigner(privKey))
suite.Require().NoError(err)
tx2 := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 1, &to, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
tx2.From = addr.Hex()
err = tx2.Sign(suite.ethSigner, tests.NewSigner(privKey))
suite.Require().NoError(err)
testCases := []struct {
name string
tx sdk.Tx
malleate func()
expPass bool
expPanic bool
}{
{
"invalid transaction type",
&invalidTx{},
func() {},
false, false,
},
{
"no signers",
evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 1, &to, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil),
func() {},
false, false,
},
{
"account not set to store",
tx,
func() {},
false, false,
},
{
"success - create contract",
contract,
func() {
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr.Bytes())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
},
true, false,
},
{
"success - call",
tx2,
func() {},
true, false,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
tc.malleate()
if tc.expPanic {
suite.Require().Panics(func() {
_, _, _ = txHandler.CheckTx(sdk.WrapSDKContext(suite.ctx), txtypes.Request{Tx: tc.tx}, txtypes.RequestCheckTx{})
})
return
}
// _, err := dec.AnteHandle(suite.ctx, tc.tx, false, nextFn)
_, _, err := txHandler.CheckTx(sdk.WrapSDKContext(suite.ctx), txtypes.Request{Tx: tc.tx}, txtypes.RequestCheckTx{})
if tc.expPass {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
if tc.expPass {
suite.Require().NoError(err)
msg := tc.tx.(*evmtypes.MsgEthereumTx)
txData, err := evmtypes.UnpackTxData(msg.Data)
suite.Require().NoError(err)
nonce := suite.app.EvmKeeper.GetNonce(suite.ctx, addr)
suite.Require().Equal(txData.GetNonce()+1, nonce)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite MiddlewareTestSuite) TestEthSetupContextDecorator() {
txHandler := middleware.ComposeMiddlewares(noopTxHandler, ante.NewEthSetUpContextMiddleware(suite.app.EvmKeeper))
tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
testCases := []struct {
name string
tx sdk.Tx
expPass bool
}{
{"invalid transaction type - does not implement GasTx", &invalidTx{}, false},
{
"success - transaction implement GasTx",
tx,
true,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
_, _, err := txHandler.CheckTx(sdk.WrapSDKContext(suite.ctx), txtypes.Request{Tx: tc.tx}, txtypes.RequestCheckTx{})
if tc.expPass {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
}