Skip to content

Commit

Permalink
feat: migration to Cosmos SDK v0.46 (#1217)
Browse files Browse the repository at this point in the history
* go.mod cosmos-sdk bump

* update migrations

* cleanups

* commenting out gov proposal handlers

* solve tendermint incompatibilities

* fix go.mod grpc imports

* use latest cosmos sdk

* bump cosmos-sdk

* fix price feeder go.mod

* bump tendermint

* fix iavl version

* update sdk and IAVL

* adding go.sum

* remove ibc-go/v2

* main go.mod tidy

* price-feeder go.mod fix

* bump Cosmos SDK

* migration p1

* migrate ibctransfer module

* update ante handler

* fix ante build

* api fix

* fix oracle simulations

* migrate app.go + upgrades

* enable nft

* fixes

* fix leverage proposal handler

* fix app export

* fix modules

* fix test_helpers and EncodingConfig

* fix cmd modules

* update changelog

* update comments in oracle keeper

* use cosmos-sdk fork

* use cosmos-sdk umee release

* update cmd root and flags

* review comments

* review

* update oracle tests

* fix oracle tests

* update sdk.Int to sdkmath.Int

* moved sdk.StoreKey to storetypes.StoreKey

* fix leverage tests by making sure the addr size is 20

* add missing param to SetupWithGenesisValSet

* fix lint

* update GetStakingKeeper to return object

* remove custom Gentx module

* migrate price-feeder for umee v3 compatibility

* add commit tag to umee-network/cosmos-sdk

* add commit tag to umee-network/ibc-go

* add commit tag to umee-network/bech32-ibc

* add commit tag to umee-network/Gravity-Bridge

* add commit tag to price-feeder

* add gowork files

* add verification to conversionRates

* add line to go.work - note that go mod verify still errors

* make go-mod-tidy

* remove deprecated grpc.WithInsecure

* fix sims - initial stake

* e2e keyring migrations

* use p2p instead of tmtypes in e2e

* review

* update ante tests

* remove unnecesassary SetupTest call

* import whitespace convention

* lint++

* remove duplicated import in ibctransfer

* Use ignite cli fork for liveness test

* fix test names which stop expected tests

* fix liveness go.work issue

* improving ante handler fee tests

* modify verification of fee and priority

* review update: use require.Equal for Int

* fix sim test

* fix sim test

* revoked to 100000 MaxMsgGasUsage

* cosmetics

* reduce free GB messages

* Update ante/fee_test.go

* fix int equality check

* fix nil pointer panic

* change group config

* fix: remove not compatible VerifyAddressFormat for sdk.Config

* fix debug cmd

* fix e2e createMemoryKeyFromMnemonic

* remove excessive config log

* add fix of output json

* add verification of err

* remove deprecated ioutil

* removed unused field/functions

* simplified gas price

* add count to check amount of tokens instead of hardcoding it

* add mock provider to peggo

* add function to check balances when sending

* simplified e2e testing sendFromEthToUmee

* simplified e2e testing sendFromUmeeToEth

* test: disable ibctransfer TestTrackMetadata

* skip 2

* update skip statement

* remove go.work

Co-authored-by: RafilxTenfen <[email protected]>
Co-authored-by: toteki <[email protected]>
Co-authored-by: Adam Wozniak <[email protected]>
  • Loading branch information
4 people authored Aug 22, 2022
1 parent e27b8fb commit 385dc5c
Show file tree
Hide file tree
Showing 74 changed files with 2,189 additions and 1,925 deletions.
9 changes: 6 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,16 @@ jobs:
- name: Install Starport
if: env.GIT_DIFF
run: |
curl https://get.ignite.com/cli! | bash
cd ../
git clone https://github.com/umee-network/cli --depth=1
cd cli && make install
cd ../umee
- name: Start Local Network via Starport
if: env.GIT_DIFF
run: |
/usr/local/bin/ignite chain serve --reset-once -v -c ./starport.ci.yml &
~/go/bin/ignite chain serve --reset-once -v -c ./starport.ci.yml &
- name: Test Local Network Liveness
if: env.GIT_DIFF
run: |
sleep 1m
./contrib/scripts/test_localnet_liveness.sh 40 5 50 localhost
./contrib/scripts/test_localnet_liveness.sh 50 5 50 localhost
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ Ref: https://keepachangelog.com/en/1.0.0/
- [1188](https://github.com/umee-network/umee/pull/1188) Add `liquidity`, `maximum_borrow`, `maximum_collateral`, `minimum_liquidity`, `available_withdraw`, `available_collateralize`, and `utoken_supply` fields to market summary.
- [1203](https://github.com/umee-network/umee/pull/1203) Add Swagger docs.
- [1212](https://github.com/umee-network/umee/pull/1212) Add `util/checkers` utility package providing common check / validation functions.
- [1217](https://github.com/umee-network/umee/pull/1217) Integrated Cosmos SDK v0.46
- Adding Cosmos SDK x/group module.
- Increased Gov `MaxMetadataLen` from 255 to 800 characters.
- [1220](https://github.com/umee-network/umee/pull/1220) Submit oracle prevotes / vote txs via the CLI.
- [1222](https://github.com/umee-network/umee/pull/1222) Liquidation reward_denom can now be either token or uToken.
- [1238](https://github.com/umee-network/umee/pull/1238) Added bad debts query.
Expand Down
25 changes: 8 additions & 17 deletions ante/ante.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,40 +22,31 @@ type HandlerOptions struct {
// signer.
func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
if options.AccountKeeper == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "account keeper is required for ante builder")
return nil, sdkerrors.ErrLogic.Wrap("account keeper is required for ante builder")
}

if options.BankKeeper == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "bank keeper is required for ante builder")
return nil, sdkerrors.ErrLogic.Wrap("bank keeper is required for ante builder")
}

if options.OracleKeeper == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "oracle keeper is required for ante builder")
return nil, sdkerrors.ErrLogic.Wrap("oracle keeper is required for ante builder")
}

if options.SignModeHandler == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "sign mode handler is required for ante builder")
}

sigGasConsumer := options.SigGasConsumer
if sigGasConsumer == nil {
sigGasConsumer = cosmosante.DefaultSigVerificationGasConsumer
return nil, sdkerrors.ErrLogic.Wrap("sign mode handler is required for ante builder")
}

return sdk.ChainAnteDecorators(
cosmosante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
cosmosante.NewRejectExtensionOptionsDecorator(),
NewMempoolFeeDecorator(), // mempool fee validation
cosmosante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
cosmosante.NewExtensionOptionsDecorator(nil), // nil=reject extensions
NewSpamPreventionDecorator(options.OracleKeeper), // spam prevention
cosmosante.NewValidateBasicDecorator(),
cosmosante.NewTxTimeoutHeightDecorator(),
cosmosante.NewValidateMemoDecorator(options.AccountKeeper),
cosmosante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
cosmosante.NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper),
cosmosante.NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, FeeAndPriority),
// SetPubKeyDecorator must be called before all signature verification decorators
cosmosante.NewSetPubKeyDecorator(options.AccountKeeper),
cosmosante.NewValidateSigCountDecorator(options.AccountKeeper),
cosmosante.NewSigGasConsumeDecorator(options.AccountKeeper, sigGasConsumer),
cosmosante.NewSigGasConsumeDecorator(options.AccountKeeper, options.SigGasConsumer),
cosmosante.NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler),
cosmosante.NewIncrementSequenceDecorator(options.AccountKeeper),
), nil
Expand Down
98 changes: 61 additions & 37 deletions ante/fee.go
Original file line number Diff line number Diff line change
@@ -1,48 +1,36 @@
package ante

import (
"math"

gbtypes "github.com/Gravity-Bridge/Gravity-Bridge/module/x/gravity/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"

oracletypes "github.com/umee-network/umee/v2/x/oracle/types"
)

// MaxOracleMsgGasUsage defines the maximum gas allowed for an oracle transaction.
const MaxOracleMsgGasUsage = uint64(100000)

// MempoolFeeDecorator defines a custom Umee AnteHandler decorator that is
// responsible for allowing oracle transactions from oracle feeders to bypass
// the minimum fee CheckTx check. However, if an oracle transaction's gas limit
// is beyond the accepted threshold, the minimum fee check is still applied.
//
// For non-oracle transactions, the minimum fee check is applied.
type MempoolFeeDecorator struct{}

func NewMempoolFeeDecorator() MempoolFeeDecorator {
return MempoolFeeDecorator{}
}
// MaxMsgGasUsage defines the maximum gas allowed for an oracle transaction.
const MaxMsgGasUsage = uint64(100000)

func (mfd MempoolFeeDecorator) AnteHandle(
ctx sdk.Context,
tx sdk.Tx,
simulate bool,
next sdk.AnteHandler,
) (newCtx sdk.Context, err error) {
// FeeAndPriority ensures tx has enough fee coins to pay for the gas at the CheckTx time
// to early remove transactions from the mempool without enough attached fee.
// The validator min fee check is ignored if the tx contains only oracle messages and
// tx gas limit is <= MaxOracleMsgGasUsage. Essentially, validators can provide price
// transactison for free as long as the gas per message is in the MaxOracleMsgGasUsage limit.
func FeeAndPriority(ctx sdk.Context, tx sdk.Tx) (sdk.Coins, int64, error) {
feeTx, ok := tx.(sdk.FeeTx)
if !ok {
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx")
return nil, 0, sdkerrors.ErrTxDecode.Wrap("Tx must be a FeeTx")
}

feeCoins := feeTx.GetFee()
gas := feeTx.GetGas()
msgs := feeTx.GetMsgs()
isOracleOrGravity := IsOracleOrGravityTx(msgs)
chargeFees := !isOracleOrGravity || gas > uint64(len(msgs))*MaxMsgGasUsage

// Only check for minimum fees if the execution mode is CheckTx and the tx does
// not contain oracle messages. If the tx does contain oracle messages, it's
// total gas must be less than or equal to a constant, otherwise minimum fees
// are checked.
if ctx.IsCheckTx() && !simulate &&
!(isOracleTx(msgs) && gas <= uint64(len(msgs))*MaxOracleMsgGasUsage) {
if ctx.IsCheckTx() && chargeFees {
minGasPrices := ctx.MinGasPrices()
if !minGasPrices.IsZero() {
requiredFees := make(sdk.Coins, len(minGasPrices))
Expand All @@ -56,26 +44,39 @@ func (mfd MempoolFeeDecorator) AnteHandle(
}

if !feeCoins.IsAnyGTE(requiredFees) {
return ctx, sdkerrors.Wrapf(
sdkerrors.ErrInsufficientFee,
"insufficient fees; got: %s required: %s",
feeCoins,
requiredFees,
)
return nil, 0, sdkerrors.ErrInsufficientFee.Wrapf(
"insufficient fees; got: %s required: %s", feeCoins, requiredFees)
}
}
}

return next(ctx, tx, simulate)
priority := getTxPriority(feeCoins, isOracleOrGravity)
if !chargeFees {
return sdk.Coins{}, priority, nil
}
return feeCoins, priority, nil
}

func isOracleTx(msgs []sdk.Msg) bool {
// IsOracleOrGravityTx checks if all messages are oracle messages
func IsOracleOrGravityTx(msgs []sdk.Msg) bool {
for _, msg := range msgs {
switch msg.(type) {
case *oracletypes.MsgAggregateExchangeRatePrevote:
case *oracletypes.MsgAggregateExchangeRatePrevote,
*oracletypes.MsgAggregateExchangeRateVote:
continue

case *oracletypes.MsgAggregateExchangeRateVote:
// TODO: remove messages which should not be "free":
case *gbtypes.MsgValsetConfirm,
*gbtypes.MsgRequestBatch,
*gbtypes.MsgConfirmBatch,
*gbtypes.MsgERC20DeployedClaim,
*gbtypes.MsgConfirmLogicCall,
*gbtypes.MsgLogicCallExecutedClaim,
*gbtypes.MsgSendToCosmosClaim,
*gbtypes.MsgExecuteIbcAutoForwards,
*gbtypes.MsgBatchSendToEthClaim,
*gbtypes.MsgValsetUpdatedClaim,
*gbtypes.MsgSubmitBadSignatureEvidence:
continue

default:
Expand All @@ -85,3 +86,26 @@ func isOracleTx(msgs []sdk.Msg) bool {

return true
}

// getTxPriority returns naive tx priority based on the lowest fee amount (regardless of the
// denom) and oracle tx check.
func getTxPriority(fee sdk.Coins, isOracleOrGravity bool) int64 {
var priority int64
for _, c := range fee {
// TODO: we should better compare amounts
// https://github.com/umee-network/umee/issues/510
p := int64(math.MaxInt64)
if c.Amount.IsInt64() {
p = c.Amount.Int64()
}
if priority == 0 || p < priority {
priority = p
}
}
if isOracleOrGravity {
// TODO: this is a naive version.
// Proper solution will be implemented in https://github.com/umee-network/umee/issues/510
priority += 100000
}
return priority
}
86 changes: 48 additions & 38 deletions ante/fee_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,61 +4,71 @@ import (
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"

"github.com/umee-network/umee/v2/ante"
oracletypes "github.com/umee-network/umee/v2/x/oracle/types"
)

func (suite *IntegrationTestSuite) TestMempoolFee() {
suite.SetupTest()
func (suite *IntegrationTestSuite) TestFeeAndPriority() {
require := suite.Require()
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()

mfd := ante.NewMempoolFeeDecorator()
antehandler := sdk.ChainAnteDecorators(mfd)
priv1, _, addr1 := testdata.KeyTestPubAddr()
privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0}

msg := testdata.NewTestMsg(addr1)
feeAmount := testdata.NewTestFeeAmount()
gasLimit := testdata.NewTestGasLimit()
suite.Require().NoError(suite.txBuilder.SetMsgs(msg))
suite.txBuilder.SetFeeAmount(feeAmount)
suite.txBuilder.SetGasLimit(gasLimit)
msgs := testdata.NewTestMsg(addr1)
require.NoError(suite.txBuilder.SetMsgs(msgs))
fee := sdk.NewCoins(sdk.NewInt64Coin("atom", 150))
gasLimit := 200000
suite.txBuilder.SetFeeAmount(fee)
suite.txBuilder.SetGasLimit(uint64(gasLimit))

privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0}
// Test1: validator min gas price check
// Ante should fail when validator min gas price is above the transaction gas limit
minGasPrice := sdk.NewDecCoinFromDec("atom", sdk.NewDecFromInt(fee[0].Amount).QuoInt64(int64(gasLimit/2)))
ctx := suite.ctx.
WithMinGasPrices([]sdk.DecCoin{minGasPrice}).
WithIsCheckTx(true)
tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
suite.Require().NoError(err)
require.NoError(err)
_, _, err = ante.FeeAndPriority(ctx, tx)
require.ErrorIs(sdkerrors.ErrInsufficientFee, err)

// Set high gas price so standard test fee fails
atomPrice := sdk.NewDecCoinFromDec("atom", sdk.NewDec(200).Quo(sdk.NewDec(100000)))
highGasPrice := []sdk.DecCoin{atomPrice}
suite.ctx = suite.ctx.WithMinGasPrices(highGasPrice)
// Test2: min gas price not checked in DeliverTx
ctx = suite.ctx.WithIsCheckTx(false)
suite.checkFeeAnte(tx, fee, ctx)

suite.ctx = suite.ctx.WithIsCheckTx(true)
// Test3: should not error when min gas price is same or lower than the fee
ctx = ctx.WithMinGasPrices(sdk.NewDecCoinsFromCoins(fee...))
suite.checkFeeAnte(tx, fee, ctx)

// antehandler errors with insufficient fees
_, err = antehandler(suite.ctx, tx, false)
suite.Require().Error(err, "Decorator should have errored on too low fee for local gasPrice")
ctx = ctx.WithMinGasPrices([]sdk.DecCoin{sdk.NewDecCoin(fee[0].Denom, fee[0].Amount.QuoRaw(2))})
suite.checkFeeAnte(tx, fee, ctx)

// ensure no fees for oracle msgs
suite.Require().NoError(suite.txBuilder.SetMsgs(
// Test4: ensure no fees for oracle msgs
require.NoError(suite.txBuilder.SetMsgs(
oracletypes.NewMsgAggregateExchangeRatePrevote(oracletypes.AggregateVoteHash{}, addr1, sdk.ValAddress(addr1)),
oracletypes.NewMsgAggregateExchangeRateVote("", "", addr1, sdk.ValAddress(addr1)),
))
suite.txBuilder.SetFeeAmount(sdk.Coins{})
suite.txBuilder.SetGasLimit(0)
oracleTx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
_, err = antehandler(suite.ctx, oracleTx, false)
suite.Require().NoError(err, "Decorator should not require high price for oracle tx")
require.NoError(err)
require.True(oracleTx.GetFee().IsZero(), "got: %s", oracleTx.GetFee())
require.Equal(uint64(0), oracleTx.GetGas())
require.True(ante.IsOracleOrGravityTx(oracleTx.GetMsgs()))

suite.ctx = suite.ctx.WithIsCheckTx(false)

// antehandler should not error since we do not check minGasPrice in DeliverTx
_, err = antehandler(suite.ctx, tx, false)
suite.Require().NoError(err, "MempoolFeeDecorator returned error in DeliverTx")

suite.ctx = suite.ctx.WithIsCheckTx(true)

atomPrice = sdk.NewDecCoinFromDec("atom", sdk.NewDec(0).Quo(sdk.NewDec(100000)))
lowGasPrice := []sdk.DecCoin{atomPrice}
suite.ctx = suite.ctx.WithMinGasPrices(lowGasPrice)
suite.checkFeeAnte(oracleTx, sdk.Coins{}, suite.ctx.WithIsCheckTx(true))
suite.checkFeeAnte(oracleTx, sdk.Coins{}, suite.ctx.WithIsCheckTx(false))
}

_, err = antehandler(suite.ctx, tx, false)
suite.Require().NoError(err, "Decorator should not have errored on fee higher than local gasPrice")
func (suite *IntegrationTestSuite) checkFeeAnte(tx sdk.Tx, feeExpected sdk.Coins, ctx sdk.Context) {
require := suite.Require()
fee, _, err := ante.FeeAndPriority(ctx, tx)
require.NoError(err)
if len(feeExpected) == 0 {
require.True(fee.IsZero(), "fee should be zero, got: %s", fee)
} else {
require.True(fee.IsEqual(feeExpected), "Fee expected %s, got: %s", feeExpected, fee)
}
}
11 changes: 8 additions & 3 deletions ante/spam_prevention.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,14 @@ func (spd *SpamPreventionDecorator) CheckOracleSpam(ctx sdk.Context, msgs []sdk.
return nil
}

func (spd *SpamPreventionDecorator) validate(ctx sdk.Context, feeder, validator string,
cache map[string]int64, curHeight int64, txType string) error {

func (spd *SpamPreventionDecorator) validate(
ctx sdk.Context,
feeder,
validator string,
cache map[string]int64,
curHeight int64,
txType string,
) error {
feederAddr, err := sdk.AccAddressFromBech32(feeder)
if err != nil {
return err
Expand Down
1 change: 0 additions & 1 deletion ante/spam_prevention_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
)

func (suite *IntegrationTestSuite) TestOracleSpam() {
suite.SetupTest()
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()

priv1, _, addr1 := testdata.KeyTestPubAddr()
Expand Down
Loading

0 comments on commit 385dc5c

Please sign in to comment.