diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 82f26d3b85f..554624d0579 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -32,7 +32,7 @@ jobs: strategy: fail-fast: false matrix: - language: [ 'go', 'python' ] + language: [ 'go' ] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] # Learn more about CodeQL language support at https://git.io/codeql-language-support @@ -42,7 +42,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -53,7 +53,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v1 + uses: github/codeql-action/autobuild@v2 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -67,4 +67,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/docker-push.yml b/.github/workflows/docker-push.yml index 2f70d2db023..552168b4b16 100644 --- a/.github/workflows/docker-push.yml +++ b/.github/workflows/docker-push.yml @@ -34,7 +34,7 @@ jobs: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - name: Build and push Docker image - uses: docker/build-push-action@1cb9d22b932e4832bb29793b7777ec860fc1cde0 + uses: docker/build-push-action@c84f38281176d4c9cdb1626ffafcd6b3911b5d94 with: context: . push: true diff --git a/Makefile b/Makefile index 4dfadb42590..77941b619f9 100644 --- a/Makefile +++ b/Makefile @@ -228,11 +228,10 @@ start-localnet-ci: ./build/gaiad keys add val --home ~/.gaiad-liveness ./build/gaiad add-genesis-account val 10000000000000000000000000stake --home ~/.gaiad-liveness --keyring-backend test ./build/gaiad gentx val 1000000000stake --home ~/.gaiad-liveness --chain-id liveness - ./build/gaiad collect-gentxs --home ~/.gaiad-liveness + ./build/gaiad collect-gentxs --home ~/.gaiad-liveness sed -i'' 's/minimum-gas-prices = ""/minimum-gas-prices = "0uatom"/' ~/.gaiad-liveness/config/app.toml ./build/gaiad start --home ~/.gaiad-liveness --x-crisis-skip-assert-invariants - .PHONY: start-localnet-ci ############################################################################### diff --git a/ante/ante.go b/ante/ante.go index 6562dea68c7..b3b49984588 100644 --- a/ante/ante.go +++ b/ante/ante.go @@ -55,6 +55,7 @@ func NewAnteHandler(opts HandlerOptions) (sdk.AnteHandler, error) { ante.NewSigGasConsumeDecorator(opts.AccountKeeper, sigGasConsumer), ante.NewSigVerificationDecorator(opts.AccountKeeper, opts.SignModeHandler), ante.NewIncrementSequenceDecorator(opts.AccountKeeper), + // todo check ibcante.NewRedundantRelayDecorator(opts.IBCkeeper), } diff --git a/ante/fee.go b/ante/fee.go index 8de301c6254..cee920edda1 100644 --- a/ante/fee.go +++ b/ante/fee.go @@ -64,7 +64,6 @@ func (mfd BypassMinFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate allowedToBypassMinFee := containsOnlyBypassMinFeeMsgs && doesNotExceedMaxGasUsage var allFees sdk.Coins - requiredFees := getMinGasPrice(ctx, feeTx) if ctx.IsCheckTx() && !simulate && !allowedToBypassMinFee { @@ -92,7 +91,7 @@ func (mfd BypassMinFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate } // bypass with fee, fee denom must in requiredGlobalFees if !DenomsSubsetOfIncludingZero(feeCoins, requiredGlobalFees) { - return ctx, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "wrong fees denom; got: %s required: %s", feeCoins, requiredGlobalFees) + return ctx, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "fees denom is wrong; got: %s required: %s", feeCoins, requiredGlobalFees) } } diff --git a/ante/fee_test.go b/ante/fee_test.go index af7e657b45b..ec1ed3b159f 100644 --- a/ante/fee_test.go +++ b/ante/fee_test.go @@ -79,11 +79,12 @@ func (s *IntegrationTestSuite) TestGlobalFeeMinimumGasFeeAnteHandler() { "empty min_gas_price, nonempty global fee, fee higher/equal than global_fee": { minGasPrice: minGasPriceEmpty, globalFeeParams: globalfeeParamsHigh, - gasPrice: sdk.NewCoins(sdk.NewCoin("uatom", highFeeAmt)), - gasLimit: testdata.NewTestGasLimit(), - txMsg: testdata.NewTestMsg(addr1), - txCheck: true, - expErr: false, + // sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()) + gasPrice: sdk.NewCoins(sdk.NewCoin("uatom", highFeeAmt)), + gasLimit: testdata.NewTestGasLimit(), + txMsg: testdata.NewTestMsg(addr1), + txCheck: true, + expErr: false, }, "empty min_gas_price, nonempty global fee, fee lower than global_fee": { minGasPrice: minGasPriceEmpty, @@ -404,7 +405,7 @@ func (s *IntegrationTestSuite) TestGlobalFeeMinimumGasFeeAnteHandler() { txCheck: true, expErr: false, }, - "globalfee contains zero coin, fee contains lower fee of zero coins's denom, globalfee also contains nonzero coin ,fee contains higher fee of nonzero coins's denom": { + "globalfee contains zero coin, fee contains lower fee of zero coins's denom, globalfee also contains nonzero coin,fee contains higher fee of nonzero coins's denom, ": { minGasPrice: minGasPrice0, globalFeeParams: globalfeeParamsContain0, gasPrice: sdk.NewCoins( diff --git a/ante/fee_utils_test.go b/ante/fee_utils_test.go index c895906b7fa..cbcdf256866 100644 --- a/ante/fee_utils_test.go +++ b/ante/fee_utils_test.go @@ -293,13 +293,11 @@ func (s *feeUtilsTestSuite) TestIsAnyGTEIncludingZero() { zeroCoinNewDenom1 := sdk.NewCoin("newphoton", sdk.NewInt(10)) zeroCoinNewDenom2 := sdk.NewCoin("newstake", sdk.NewInt(20)) zeroCoinNewDenom3 := sdk.NewCoin("newquark", sdk.NewInt(30)) - // coinNewDenom1Zero := sdk.NewCoin("newphoton", sdk.ZeroInt()) // coins must be valid !!! and sorted!!! coinsAllZero := sdk.Coins{zeroCoin1, zeroCoin2, zeroCoin3}.Sort() coinsAllNewDenomAllZero := sdk.Coins{zeroCoinNewDenom1, zeroCoinNewDenom2, zeroCoinNewDenom3}.Sort() coinsAllZeroShort := sdk.Coins{zeroCoin1, zeroCoin2}.Sort() coinsContainZero := sdk.Coins{zeroCoin1, zeroCoin2, coin3}.Sort() - // coinsContainZeroNewDenoms := sdk.Coins{zeroCoin1, zeroCoin2, coinNewDenom1Zero}.Sort() coins := sdk.Coins{coin1, coin2, coin3}.Sort() coinsHighHigh := sdk.Coins{coin1High, coin2High} diff --git a/app/app.go b/app/app.go index c1cd30e95b2..52ed7992033 100644 --- a/app/app.go +++ b/app/app.go @@ -82,7 +82,6 @@ import ( upgradeclient "github.com/cosmos/cosmos-sdk/x/upgrade/client" upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" - "github.com/cosmos/gaia/v8/x/globalfee" ica "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts" icacontrollertypes "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/controller/types" icahost "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/host" @@ -117,6 +116,7 @@ import ( gaiaante "github.com/cosmos/gaia/v8/ante" gaiaappparams "github.com/cosmos/gaia/v8/app/params" + "github.com/cosmos/gaia/v8/x/globalfee" // unnamed import of statik for swagger UI support _ "github.com/cosmos/cosmos-sdk/client/docs/statik" @@ -543,6 +543,7 @@ func NewGaiaApp( liquidity.NewAppModule(appCodec, app.LiquidityKeeper, app.AccountKeeper, app.BankKeeper, app.DistrKeeper), transferModule, icaModule, + routerModule, globalfee.NewAppModule(app.GetSubspace(globalfee.ModuleName)), routerModule, ) diff --git a/contrib/generate_release_note/main.go b/contrib/generate_release_note/main.go index 75b5203471a..2d712b915d2 100644 --- a/contrib/generate_release_note/main.go +++ b/contrib/generate_release_note/main.go @@ -1,4 +1,5 @@ -// go:build exclude +//go:build exclude +// +build exclude package main diff --git a/docs/interchain-security.md b/docs/interchain-security.md index 7c7e25553e7..7c597f2d82c 100644 --- a/docs/interchain-security.md +++ b/docs/interchain-security.md @@ -103,7 +103,7 @@ To distinguish fees in a Partial Validator Set (Opt-In), the distribution module ## IBC & Cross Chain Validation -There are a number of IBC application layer modules and packets that need to be developed to fully realize the IBC component of Interchain Security. This work has begun with a spec draft from Informal Systems that is visible at [@ibc/cross-chain-validation](https://github.com/cosmos/ibc/tree/marius/ccv/spec/app/ics-028-cross-chain-validation). Instead of diving into the details of what they are and exactly how they work this section will be reserved for high level responsibilities of these mechanisms. +There are a number of IBC application layer modules and packets that need to be developed to fully realize the IBC component of Interchain Security. This work has begun with a spec draft from Informal Systems that is visible at [@ibc/cross-chain-validation](https://github.com/cosmos/ibc/tree/main/spec/app/ics-028-cross-chain-validation). Instead of diving into the details of what they are and exactly how they work this section will be reserved for high level responsibilities of these mechanisms. There are three types of operations within Cross Chain Validation which must be present for Interchain Security to take place: diff --git a/go.mod b/go.mod index 519c78787e4..84f05c5d20d 100644 --- a/go.mod +++ b/go.mod @@ -18,14 +18,11 @@ require ( github.com/stretchr/testify v1.8.0 github.com/tendermint/tendermint v0.34.20 github.com/tendermint/tm-db v0.6.7 - google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd - google.golang.org/grpc v1.48.0 -) - -require ( github.com/gogo/protobuf v1.3.3 github.com/golang/protobuf v1.5.2 github.com/grpc-ecosystem/grpc-gateway v1.16.0 + google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd + google.golang.org/grpc v1.48.0 ) require ( diff --git a/go.work.sum b/go.work.sum index 951ec4ee070..663aa54665b 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,75 +1,3 @@ -bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= -cosmossdk.io/api v0.1.0-alpha8/go.mod h1:gIs3NW5OSNK5wKqxF8JHnGTL82QMsXpwGeKmu2i5xFA= -cosmossdk.io/errors v1.0.0-beta.6/go.mod h1:mz6FQMJRku4bY7aqS/Gwfcmr/ue91roMEKAmDUDpBfE= cosmossdk.io/math v1.0.0-beta.2/go.mod h1:u/MXvf8wbUbCsAEyQSSYXXMsczAsFX48e2D6JI86T4o= -github.com/99designs/keyring v1.1.6/go.mod h1:16e0ds7LGQQcT59QqkTg72Hh5ShM51Byv5PEmW6uoRU= -github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/adlio/schema v1.3.0/go.mod h1:51QzxkpeFs6lRY11kPye26IaFPOV+HqEj01t5aXXKfs= -github.com/armon/go-metrics v0.3.11/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= -github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= -github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= -github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= -github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= -github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= -github.com/containerd/continuity v0.2.1/go.mod h1:wCYX+dRqZdImhGucXOqTQn05AhX6EUDaGEMUzTFFpLg= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/cosmos/cosmos-sdk v0.46.0-rc1.0.20220616181117-53d0cc919f1a/go.mod h1:Ch4QFoljBcroLele1DOgAe6Enxh9aQZ4efu68jGrJ9E= -github.com/cosmos/cosmos-sdk/db v1.0.0-beta.1/go.mod h1:JUMM2MxF9wuwzRWZJjb8BjXsn1BmPmdBd3a75pIct4I= -github.com/cosmos/iavl v0.18.0/go.mod h1:L0VZHfq0tqMNJvXlslGExaaiZM7eSm+90Vh9QUbp6j4= -github.com/cosmos/ibc-go/v3 v3.0.0-alpha1.0.20220530074104-c7c115244bad/go.mod h1:xsWQXKbydQ0px9z1tuOhHVKLohTUbRd1G+S0sjKdnX8= -github.com/creachadair/atomicfile v0.2.6/go.mod h1:BRq8Une6ckFneYXZQ+kO7p1ZZP3I2fzVzf28JxrIkBc= -github.com/creachadair/command v0.0.0-20220426235536-a748effdf6a1/go.mod h1:bAM+qFQb/KwWyCc9MLC4U1jvn3XyakqP5QRkds5T6cY= -github.com/creachadair/taskgroup v0.3.2/go.mod h1:wieWwecHVzsidg2CsUnFinW1faVN4+kq+TDlRJQ0Wbk= -github.com/creachadair/tomledit v0.0.22/go.mod h1:cIu/4x5L855oSRejIqr+WRFh+mv9g4fWLiUFaApYn/Y= -github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= -github.com/danieljoos/wincred v1.0.2/go.mod h1:SnuYRW9lp1oJrZX/dXJqr0cPK5gYXqx3EJbmjhLdK9U= -github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM= -github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= -github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golangci/golangci-lint v1.46.0/go.mod h1:IJpcNOUfx/XLRwE95FHQ6QtbhYwwqcm0H5QkwUfF4ZE= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gravity-devs/liquidity/v2 v2.0.0-rc1/go.mod h1:RibbX8H7R3+5sqfrs1Qgv0UJrNCcP55/vSNXRvQZTIg= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d/go.mod h1:JJNrCn9otv/2QP4D7SMJBgaleKpOf66PnW6F5WGNRIc= -github.com/lazyledger/smt v0.2.1-0.20210709230900-03ea40719554/go.mod h1:9+Pb2/tg1PvEgW7aFx4bFhDE4bvbI03zuJ8kb7nJ9Jc= -github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= -github.com/lufeee/execinquery v1.0.0/go.mod h1:EC7DrEKView09ocscGHC+apXMIaorh4xqSxS/dy8SbM= -github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= -github.com/mroth/weightedrand v0.4.1/go.mod h1:3p2SIcC8al1YMzGhAIoXD+r9olo/g/cdJgAD905gyNE= -github.com/oasisprotocol/curve25519-voi v0.0.0-20210609091139-0a56a4bca00b/go.mod h1:TLJifjWF6eotcfzDjKZsDqWJ+73Uvj/N85MvVyrvynM= -github.com/opencontainers/runc v1.0.3/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= -github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= -github.com/polyfloyd/go-errorlint v0.0.0-20211125173453-6d6d39c5bb8b/go.mod h1:wi9BfjxjF/bwiZ701TzmfKu6UKC357IOAtNr0Td0Lvw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/rs/zerolog v1.26.1/go.mod h1:/wSSJWX7lVrsOwlbyTRSOJvqRlc+WjWlfes+CiJ+tmc= -github.com/sagikazarmark/crypt v0.4.0/go.mod h1:ALv2SRj7GxYV4HO9elxH9nS6M9gW+xDNxqmyJ6RfDFM= -github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= -github.com/spf13/afero v1.8.0/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= -github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/tendermint/tendermint v0.34.19/go.mod h1:R5+wgIwSxMdKQcmOaeudL0Cjkr3HDkhpcdum6VeU3R4= -github.com/tendermint/tendermint v0.35.6/go.mod h1:2hAS7fqHf1/XusWqSl5m7MOrXeptvYVeHpkPup/CAJg= -github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/vektra/mockery/v2 v2.12.3/go.mod h1:8vf4KDDUptfkyypzdHLuE7OE2xA7Gdt60WgIS8PgD+U= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5 h1:FR+oGxGfbQu1d+jglI3rCkjAjUnhRSZcUxr+DqlDLNo= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20211208012354-db4efeb81f4b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -gopkg.in/ini.v1 v1.66.3/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= diff --git a/tests/e2e/e2e_cli_util.go b/tests/e2e/e2e_cli_util.go index 7e5165be5a4..5903b3a06a9 100644 --- a/tests/e2e/e2e_cli_util.go +++ b/tests/e2e/e2e_cli_util.go @@ -10,6 +10,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" + + globalfee "github.com/cosmos/gaia/v8/x/globalfee/types" ) func queryGaiaTx(endpoint, txHash string) error { @@ -37,6 +39,7 @@ func queryGaiaTx(endpoint, txHash string) error { return nil } +// if coin is zero, return empty coin. func getSpecificBalance(endpoint, addr, denom string) (amt sdk.Coin, err error) { balances, err := queryGaiaAllBalances(endpoint, addr) if err != nil { @@ -115,11 +118,31 @@ func queryGovProposal(endpoint string, proposalID int) (govv1beta1.QueryProposal if err != nil { return emptyProp, err } - var govProposalResp govv1beta1.QueryProposalResponse + var govProposalResp govv1beta1.QueryProposalResponse if err := cdc.UnmarshalJSON(body, &govProposalResp); err != nil { return emptyProp, err } return govProposalResp, nil } + +func queryGlobalFees(endpoint string) (amt sdk.DecCoins, err error) { + resp, err := http.Get(fmt.Sprintf("%s/gaia/globalfee/v1beta1/minimum_gas_prices", endpoint)) + if err != nil { + return nil, fmt.Errorf("failed to execute HTTP request: %w", err) + } + defer resp.Body.Close() + + bz, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + var fees globalfee.QueryMinimumGasPricesResponse + if err := cdc.UnmarshalJSON(bz, &fees); err != nil { + return sdk.DecCoins{}, err + } + + return fees.MinimumGasPrices, nil +} diff --git a/tests/e2e/e2e_setup_test.go b/tests/e2e/e2e_setup_test.go index 2783074b6bc..409ad82db1c 100644 --- a/tests/e2e/e2e_setup_test.go +++ b/tests/e2e/e2e_setup_test.go @@ -17,15 +17,17 @@ import ( "time" "cosmossdk.io/math" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - "github.com/cosmos/cosmos-sdk/server" srvconfig "github.com/cosmos/cosmos-sdk/server/config" sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/cosmos/gaia/v8/app/params" + ibcclienttypes "github.com/cosmos/ibc-go/v5/modules/core/02-client/types" + ibcchanneltypes "github.com/cosmos/ibc-go/v5/modules/core/04-channel/types" "github.com/ory/dockertest/v3" "github.com/ory/dockertest/v3/docker" "github.com/spf13/viper" @@ -36,9 +38,16 @@ import ( ) const ( - uatomDenom = "uatom" - initBalanceStr = "110000000000stake,100000000000000000uatom" - minGasPrice = "0.00001" + photonDenom = "photon" + uatomDenom = "uatom" + initBalanceStr = "110000000000stake,100000000000000000photon,100000000000000000uatom" + minGasPrice = "0.00001" + // the test globalfee in genesis is the same as minGasPrice + // global fee lower/higher than min_gas_price + initialGlobalFeeAmt = "0.00001" + lowGlobalFeesAmt = "0.000001" + highGlobalFeeAmt = "0.0001" + gas = 200000 govSendMsgRecipientAddress = "cosmos1pkueemdeps77dwrqma03pwqk93nw39nuhccz02" govProposalBlockBuffer = 35 ) @@ -167,7 +176,7 @@ func (s *IntegrationTestSuite) initNodes(c *chain) { address, err := val.keyInfo.GetAddress() s.Require().NoError(err) s.Require().NoError( - addGenesisAccount(val0ConfigDir, "", initBalanceStr, address), + modifyGenesis(val0ConfigDir, "", initBalanceStr, address, initialGlobalFeeAmt+uatomDenom), ) } @@ -294,7 +303,31 @@ func (s *IntegrationTestSuite) initValidatorConfigs(c *chain) { appConfig.API.Enable = true appConfig.MinGasPrices = fmt.Sprintf("%s%s", minGasPrice, uatomDenom) - srvconfig.WriteConfigFile(appCfgPath, appConfig) + // srvconfig.WriteConfigFile(appCfgPath, appConfig) + appCustomConfig := params.CustomAppConfig{ + Config: *appConfig, + BypassMinFeeMsgTypes: []string{ + // todo: use ibc as exmaple ? + sdk.MsgTypeURL(&ibcchanneltypes.MsgRecvPacket{}), + sdk.MsgTypeURL(&ibcchanneltypes.MsgAcknowledgement{}), + sdk.MsgTypeURL(&ibcclienttypes.MsgUpdateClient{}), + "/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward", + }, + } + + customAppTemplate := ` +############################################################################### +### Custom Gaia Configuration ### +############################################################################### +# bypass-min-fee-msg-types defines custom message types the operator may set that +# will bypass minimum fee checks during CheckTx. +# +# Example: +# ["/ibc.core.channel.v1.MsgRecvPacket", "/ibc.core.channel.v1.MsgAcknowledgement", ...] +bypass-min-fee-msg-types = ["/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward","/ibc.applications.transfer.v1.MsgTransfer"] +` + srvconfig.DefaultConfigTemplate + srvconfig.SetConfigTemplate(customAppTemplate) + srvconfig.WriteConfigFile(appCfgPath, appCustomConfig) } } @@ -556,3 +589,35 @@ func (s *IntegrationTestSuite) writeGovUpgradeSoftwareProposal(c *chain, height err = writeFile(filepath.Join(c.validators[0].configDir(), "config", "proposal_4.json"), cancelUpgradeProposalBody) s.Require().NoError(err) } + +func (s *IntegrationTestSuite) writeGovParamChangeProposalGlobalFees(c *chain, coins sdk.DecCoins) { + type ParamInfo struct { + Subspace string `json:"subspace"` + Key string `json:"key"` + Value sdk.DecCoins `json:"value"` + } + + type ParamChangeMessage struct { + Title string `json:"title"` + Description string `json:"description"` + Changes []ParamInfo `json:"changes"` + Deposit string `json:"deposit"` + } + + paramChangeProposalBody, err := json.MarshalIndent(ParamChangeMessage{ + Title: "global fee test", + Description: "global fee change", + Changes: []ParamInfo{ + { + Subspace: "globalfee", + Key: "MinimumGasPricesParam", + Value: coins, + }, + }, + Deposit: "", + }, "", " ") + s.Require().NoError(err) + + err = writeFile(filepath.Join(c.validators[0].configDir(), "config", "proposal_globalfee.json"), paramChangeProposalBody) + s.Require().NoError(err) +} diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 5281f6c18b5..1196ce7d9b1 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -30,8 +30,7 @@ func (s *IntegrationTestSuite) TestIBCTokenTransfer() { func() bool { balances, err = queryGaiaAllBalances(chainBAPIEndpoint, recipient) s.Require().NoError(err) - - return balances.Len() == 3 + return balances.Len() != 0 }, time.Minute, 5*time.Second, @@ -39,6 +38,7 @@ func (s *IntegrationTestSuite) TestIBCTokenTransfer() { for _, c := range balances { if strings.Contains(c.Denom, "ibc/") { + fmt.Print("c.denom:", c.Denom, "c.amount:", c.Amount) ibcStakeDenom = c.Denom s.Require().Equal(tokenAmount.Amount.Int64(), c.Amount.Int64()) break @@ -50,7 +50,7 @@ func (s *IntegrationTestSuite) TestIBCTokenTransfer() { } func (s *IntegrationTestSuite) TestBankTokenTransfer() { - s.Run("send_uatom_between_accounts", func() { + s.Run("send_photon_between_accounts", func() { var err error senderAddress, err := s.chainA.validators[0].keyInfo.GetAddress() @@ -82,7 +82,7 @@ func (s *IntegrationTestSuite) TestBankTokenTransfer() { 5*time.Second, ) - s.sendMsgSend(s.chainA, 0, sender, recipient, tokenAmount.String(), fees.String()) + s.sendMsgSend(s.chainA, 0, sender, recipient, tokenAmount.String(), fees.String(), false) s.Require().Eventually( func() bool { @@ -117,9 +117,9 @@ func (s *IntegrationTestSuite) TestSendTokensFromNewGovAccount() { s.T().Logf("Submitting Legacy Gov Proposal: Community Spend Funding Gov Module") s.submitLegacyProposalFundGovAccount(chainAAPIEndpoint, sender, proposalCounter) s.T().Logf("Depositing Legacy Gov Proposal: Community Spend Funding Gov Module") - s.depositGovProposal(chainAAPIEndpoint, sender, proposalCounter) + s.depositGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter) s.T().Logf("Voting Legacy Gov Proposal: Community Spend Funding Gov Module") - s.voteGovProposal(chainAAPIEndpoint, sender, proposalCounter, "yes", false) + s.voteGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter, "yes", false) initialGovBalance, err := getSpecificBalance(chainAAPIEndpoint, govModuleAddress, uatomDenom) s.Require().NoError(err) @@ -128,9 +128,9 @@ func (s *IntegrationTestSuite) TestSendTokensFromNewGovAccount() { s.T().Logf("Submitting Gov Proposal: Sending Tokens from Gov Module to Recipient") s.submitNewGovProposal(chainAAPIEndpoint, sender, proposalCounter, "/root/.gaia/config/proposal_2.json") s.T().Logf("Depositing Gov Proposal: Sending Tokens from Gov Module to Recipient") - s.depositGovProposal(chainAAPIEndpoint, sender, proposalCounter) + s.depositGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter) s.T().Logf("Voting Gov Proposal: Sending Tokens from Gov Module to Recipient") - s.voteGovProposal(chainAAPIEndpoint, sender, proposalCounter, "yes", false) + s.voteGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter, "yes", false) s.Require().Eventually( func() bool { newGovBalance, err := getSpecificBalance(chainAAPIEndpoint, govModuleAddress, uatomDenom) @@ -160,9 +160,9 @@ func (s *IntegrationTestSuite) TestGovSoftwareUpgrade() { s.T().Logf("Submitting Gov Proposal: Software Upgrade") s.submitNewGovProposal(chainAAPIEndpoint, sender, proposalCounter, "/root/.gaia/config/proposal_3.json") s.T().Logf("Depositing Gov Proposal: Software Upgrade") - s.depositGovProposal(chainAAPIEndpoint, sender, proposalCounter) + s.depositGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter) s.T().Logf("Weighted Voting Gov Proposal: Software Upgrade") - s.voteGovProposal(chainAAPIEndpoint, sender, proposalCounter, "yes=0.8,no=0.1,abstain=0.05,no_with_veto=0.05", true) + s.voteGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter, "yes=0.8,no=0.1,abstain=0.05,no_with_veto=0.05", true) s.verifyChainHaltedAtUpgradeHeight(s.chainA, 0, proposalHeight) s.T().Logf("Successfully halted chain at height %d", proposalHeight) @@ -202,15 +202,15 @@ func (s *IntegrationTestSuite) TestGovCancelSoftwareUpgrade() { s.T().Logf("Submitting Gov Proposal: Software Upgrade") s.submitNewGovProposal(chainAAPIEndpoint, sender, proposalCounter, "/root/.gaia/config/proposal_3.json") - s.depositGovProposal(chainAAPIEndpoint, sender, proposalCounter) - s.voteGovProposal(chainAAPIEndpoint, sender, proposalCounter, "yes", false) + s.depositGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter) + s.voteGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter, "yes", false) proposalCounter++ s.T().Logf("Submitting Gov Proposal: Cancel Software Upgrade") s.submitNewGovProposal(chainAAPIEndpoint, sender, proposalCounter, "/root/.gaia/config/proposal_4.json") - s.depositGovProposal(chainAAPIEndpoint, sender, proposalCounter) - s.voteGovProposal(chainAAPIEndpoint, sender, proposalCounter, "yes", false) + s.depositGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter) + s.voteGovProposal(chainAAPIEndpoint, sender, fees.String(), proposalCounter, "yes", false) s.verifyChainPassesUpgradeHeight(s.chainA, 0, proposalHeight) s.T().Logf("Successfully canceled upgrade at height %d", proposalHeight) @@ -218,26 +218,26 @@ func (s *IntegrationTestSuite) TestGovCancelSoftwareUpgrade() { func (s *IntegrationTestSuite) fundCommunityPool(chainAAPIEndpoint, sender string) { s.Run("fund_community_pool", func() { - beforeDistUAtomBalance, _ := getSpecificBalance(chainAAPIEndpoint, distModuleAddress, tokenAmount.Denom) - if beforeDistUAtomBalance.IsNil() { + beforeDistUatomBalance, _ := getSpecificBalance(chainAAPIEndpoint, distModuleAddress, tokenAmount.Denom) + if beforeDistUatomBalance.IsNil() { // Set balance to 0 if previous balance does not exist - beforeDistUAtomBalance = sdk.NewInt64Coin("uatom", 0) + beforeDistUatomBalance = sdk.NewInt64Coin(uatomDenom, 0) } s.execDistributionFundCommunityPool(s.chainA, 0, chainAAPIEndpoint, sender, tokenAmount.String(), fees.String()) // there are still tokens being added to the community pool through block production rewards but they should be less than 500 tokens - marginOfErrorForBlockReward := sdk.NewInt64Coin("uatom", 500) + marginOfErrorForBlockReward := sdk.NewInt64Coin(uatomDenom, 500) s.Require().Eventually( func() bool { - afterDistUAtomBalance, err := getSpecificBalance(chainAAPIEndpoint, distModuleAddress, tokenAmount.Denom) + afterDistPhotonBalance, err := getSpecificBalance(chainAAPIEndpoint, distModuleAddress, tokenAmount.Denom) if err != nil { - s.T().Logf("Error getting balance: %s", afterDistUAtomBalance) + s.T().Logf("Error getting balance: %s", afterDistPhotonBalance) } s.Require().NoError(err) - return afterDistUAtomBalance.Sub(beforeDistUAtomBalance.Add(tokenAmount.Add(fees))).IsLT(marginOfErrorForBlockReward) + return afterDistPhotonBalance.Sub(beforeDistUatomBalance.Add(tokenAmount.Add(fees))).IsLT(marginOfErrorForBlockReward) }, 15*time.Second, 5*time.Second, @@ -262,6 +262,22 @@ func (s *IntegrationTestSuite) submitLegacyProposalFundGovAccount(chainAAPIEndpo }) } +func (s *IntegrationTestSuite) submitLegacyGovProposal(chainAAPIEndpoint string, sender string, fees string, proposalTypeSubCmd string, proposalId int, proposalPath string) { + s.Run("submit_legacy_gov_proposal", func() { + s.execGovSubmitLegacyGovProposal(s.chainA, 0, chainAAPIEndpoint, sender, proposalPath, fees, proposalTypeSubCmd) + + s.Require().Eventually( + func() bool { + proposal, err := queryGovProposal(chainAAPIEndpoint, proposalId) + s.Require().NoError(err) + return (proposal.GetProposal().Status == govv1beta1.StatusDepositPeriod) + }, + 15*time.Second, + 5*time.Second, + ) + }) +} + func (s *IntegrationTestSuite) submitNewGovProposal(chainAAPIEndpoint, sender string, proposalId int, proposalPath string) { s.Run("submit_new_gov_proposal", func() { s.execGovSubmitProposal(s.chainA, 0, chainAAPIEndpoint, sender, proposalPath, fees.String()) @@ -280,9 +296,9 @@ func (s *IntegrationTestSuite) submitNewGovProposal(chainAAPIEndpoint, sender st }) } -func (s *IntegrationTestSuite) depositGovProposal(chainAAPIEndpoint, sender string, proposalId int) { +func (s *IntegrationTestSuite) depositGovProposal(chainAAPIEndpoint, sender string, fees string, proposalId int) { s.Run("deposit_gov_proposal", func() { - s.execGovDepositProposal(s.chainA, 0, chainAAPIEndpoint, sender, proposalId, depositAmount.String(), fees.String()) + s.execGovDepositProposal(s.chainA, 0, chainAAPIEndpoint, sender, proposalId, depositAmount.String(), fees) s.Require().Eventually( func() bool { @@ -297,12 +313,12 @@ func (s *IntegrationTestSuite) depositGovProposal(chainAAPIEndpoint, sender stri }) } -func (s *IntegrationTestSuite) voteGovProposal(chainAAPIEndpoint, sender string, proposalId int, vote string, weighted bool) { +func (s *IntegrationTestSuite) voteGovProposal(chainAAPIEndpoint, sender string, fees string, proposalId int, vote string, weighted bool) { s.Run("vote_gov_proposal", func() { if weighted { - s.execGovWeightedVoteProposal(s.chainA, 0, chainAAPIEndpoint, sender, proposalId, vote, fees.String()) + s.execGovWeightedVoteProposal(s.chainA, 0, chainAAPIEndpoint, sender, proposalId, vote, fees) } else { - s.execGovVoteProposal(s.chainA, 0, chainAAPIEndpoint, sender, proposalId, vote, fees.String()) + s.execGovVoteProposal(s.chainA, 0, chainAAPIEndpoint, sender, proposalId, vote, fees) } s.Require().Eventually( @@ -358,3 +374,369 @@ func (s *IntegrationTestSuite) verifyChainPassesUpgradeHeight(c *chain, valIdx, 5*time.Second, ) } + +// globalfee in genesis is set to be "0.00001photon" +func (s *IntegrationTestSuite) TestQueryGlobalFeesInGenesis() { + chainAAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chainA.id][0].GetHostPort("1317/tcp")) + feeInGenesis, err := sdk.ParseDecCoins(initialGlobalFeeAmt + uatomDenom) + s.Require().NoError(err) + s.Require().Eventually( + func() bool { + fees, err := queryGlobalFees(chainAAPIEndpoint) + s.T().Logf("Global Fees in Genesis: %s", fees.String()) + s.Require().NoError(err) + + return fees.IsEqual(feeInGenesis) + }, + 15*time.Second, + 5*time.Second, + ) +} + +/* +global fee in genesis is "0.00001uatom", which is the same as min_gas_price. +This initial value setup is for not to fail other e2e tests. +global fee e2e tests: +0. initial globalfee = 0.00001uatom, min_gas_price = 0.00001uatom + +test1. gov proposal globalfee = [], min_gas_price=0.00001uatom, query globalfee still get empty + - tx with fee denom photon, fail + - tx with zero fee denom photon, fail + - tx with fee denom uatom, pass + - tx with fee empty, fail + +test2. gov propose globalfee = 0.000001uatom(lower than min_gas_price) + - tx with fee higher than 0.000001uatom but lower than 0.00001uatom, fail + - tx with fee higher than/equal to 0.00001uatom, pass + - tx with fee photon fail + +test3. gov propose globalfee = 0.0001uatom (higher than min_gas_price) + - tx with fee equal to 0.0001uatom, pass + - tx with fee equal to 0.00001uatom, fail + +test4. gov propose globalfee = 0.000001uatom (lower than min_gas_price), 0photon + - tx with fee 0.0000001photon, fail + - tx with fee 0.000001photon, pass + - tx with empty fee, pass + - tx with fee photon pass + - tx with fee 0photon, 0.000005uatom fail + - tx with fee 0photon, 0.00001uatom pass +5. check balance correct: all the sucessful tx sent token amt is received +6. gov propose change back to initial globalfee = 0.00001photon, This is for not influence other e2e tests. +*/ +func (s *IntegrationTestSuite) TestGlobalFees() { + chainAAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chainA.id][0].GetHostPort("1317/tcp")) + + submitterAddr, err := s.chainA.validators[0].keyInfo.GetAddress() + s.Require().NoError(err) + submitter := submitterAddr.String() + recipientAddress, err := s.chainA.validators[1].keyInfo.GetAddress() + s.Require().NoError(err) + recipient := recipientAddress.String() + var beforeRecipientPhotonBalance sdk.Coin + s.Require().Eventually( + func() bool { + beforeRecipientPhotonBalance, err = getSpecificBalance(chainAAPIEndpoint, recipient, photonDenom) + s.Require().NoError(err) + + return beforeRecipientPhotonBalance.IsValid() + }, + 10*time.Second, + 5*time.Second, + ) + if beforeRecipientPhotonBalance.Equal(sdk.Coin{}) { + beforeRecipientPhotonBalance = sdk.NewCoin(photonDenom, sdk.ZeroInt()) + } + + sendAmt := int64(1000) + token := sdk.NewInt64Coin(photonDenom, sendAmt) // send 1000photon each time + sucessBankSendCount := 0 + // ---------------------------- test1: globalfee empty -------------------------------------------- + // prepare gov globalfee proposal + emptyGlobalFee := sdk.DecCoins{} + s.writeGovParamChangeProposalGlobalFees(s.chainA, emptyGlobalFee) + + // gov proposing new fees + proposalCounter++ + s.T().Logf("Proposal number: %d", proposalCounter) + s.T().Logf("Submitting, deposit and vote legacy Gov Proposal: change global fees empty") + s.submitLegacyGovProposal(chainAAPIEndpoint, submitter, fees.String(), "param-change", proposalCounter, "/root/.gaia/config/proposal_globalfee.json") + s.depositGovProposal(chainAAPIEndpoint, submitter, fees.String(), proposalCounter) + s.voteGovProposal(chainAAPIEndpoint, submitter, fees.String(), proposalCounter, "yes", false) + + // query the proposal status and new fee + s.Require().Eventually( + func() bool { + proposal, err := queryGovProposal(chainAAPIEndpoint, proposalCounter) + s.Require().NoError(err) + return (proposal.GetProposal().Status == govv1beta1.StatusPassed) + }, + 15*time.Second, + 5*time.Second, + ) + var globalFees sdk.DecCoins + s.Require().Eventually( + func() bool { + globalFees, err = queryGlobalFees(chainAAPIEndpoint) + s.T().Logf("After gov new global fee proposal: %s", globalFees.String()) + s.Require().NoError(err) + + // attention: when global fee is empty, when query, it shows empty rather than default ante.DefaultZeroGlobalFee() = 0uatom. + return globalFees.IsEqual(emptyGlobalFee) + }, + 15*time.Second, + 5*time.Second, + ) + + paidFeeAmt := sdk.MustNewDecFromStr(minGasPrice).Mul(sdk.NewDec(gas)).String() + + s.T().Logf("test case: empty global fee, globalfee=%s, min_gas_price=%s", globalFees.String(), minGasPrice+uatomDenom) + s.T().Logf("Tx fee is zero coin with correct denom: uatom, fail") + s.sendMsgSend(s.chainA, 0, submitter, recipient, token.String(), "0"+uatomDenom, true) + s.T().Logf("Tx fee is empty, fail") + s.sendMsgSend(s.chainA, 0, submitter, recipient, token.String(), "", true) + s.T().Logf("Tx with wrong denom: photon, fail") + s.sendMsgSend(s.chainA, 0, submitter, recipient, token.String(), "4"+photonDenom, true) + s.T().Logf("Tx fee is zero coins of wrong denom: photon, fail") + s.sendMsgSend(s.chainA, 0, submitter, recipient, token.String(), "0"+photonDenom, true) + s.T().Logf("Tx fee is higher than min_gas_price, pass") + s.sendMsgSend(s.chainA, 0, submitter, recipient, token.String(), paidFeeAmt+uatomDenom, false) + sucessBankSendCount++ + + // ------------------ test2: globalfee lower than min_gas_price ----------------------------------- + // prepare gov globalfee proposal + lowGlobalFee := sdk.DecCoins{sdk.NewDecCoinFromDec(uatomDenom, sdk.MustNewDecFromStr(lowGlobalFeesAmt))} + s.writeGovParamChangeProposalGlobalFees(s.chainA, lowGlobalFee) + + // gov proposing new fees + proposalCounter++ + s.T().Logf("Proposal number: %d", proposalCounter) + s.T().Logf("Submitting, deposit and vote legacy Gov Proposal: change global fees empty") + s.submitLegacyGovProposal(chainAAPIEndpoint, submitter, fees.String(), "param-change", proposalCounter, "/root/.gaia/config/proposal_globalfee.json") + s.depositGovProposal(chainAAPIEndpoint, submitter, fees.String(), proposalCounter) + s.voteGovProposal(chainAAPIEndpoint, submitter, fees.String(), proposalCounter, "yes", false) + + // query the proposal status and new fee + s.Require().Eventually( + func() bool { + proposal, err := queryGovProposal(chainAAPIEndpoint, proposalCounter) + s.Require().NoError(err) + return (proposal.GetProposal().Status == govv1beta1.StatusPassed) + }, + 15*time.Second, + 5*time.Second, + ) + + s.Require().Eventually( + func() bool { + globalFees, err := queryGlobalFees(chainAAPIEndpoint) + s.T().Logf("After gov new global fee proposal: %s", globalFees.String()) + s.Require().NoError(err) + + return globalFees.IsEqual(lowGlobalFee) + }, + 15*time.Second, + 5*time.Second, + ) + + paidFeeAmt = sdk.MustNewDecFromStr(minGasPrice).Mul(sdk.NewDec(gas)).String() + paidFeeAmtLowMinGasHighGlobalFee := sdk.MustNewDecFromStr(lowGlobalFeesAmt).Mul(sdk.NewDec(2)).Mul(sdk.NewDec(gas)).String() + paidFeeAmtLowGLobalFee := sdk.MustNewDecFromStr(lowGlobalFeesAmt).Quo(sdk.NewDec(2)).String() + + s.T().Logf("test case: global fee is lower than min_gas_price, globalfee=%s, min_gas_price=%s", globalFees.String(), minGasPrice+uatomDenom) + s.T().Logf("Tx fee higher than/equal to min_gas_price and global fee, pass") + s.sendMsgSend(s.chainA, 0, submitter, recipient, token.String(), paidFeeAmt+uatomDenom, false) + sucessBankSendCount++ + s.T().Logf("Tx fee lower than/equal to min_gas_price and global fee, pass") + s.sendMsgSend(s.chainA, 0, submitter, recipient, token.String(), paidFeeAmtLowGLobalFee+uatomDenom, true) + s.T().Logf("Tx fee lower than/equal global fee and lower than min_gas_price, fail") + s.sendMsgSend(s.chainA, 0, submitter, recipient, token.String(), paidFeeAmtLowMinGasHighGlobalFee+uatomDenom, true) + s.T().Logf("Tx fee has wrong denom, fail") + s.sendMsgSend(s.chainA, 0, submitter, recipient, token.String(), paidFeeAmt+photonDenom, true) + + // ------------------ test3: globalfee higher than min_gas_price ---------------------------------- + // prepare gov globalfee proposal + highGlobalFee := sdk.DecCoins{sdk.NewDecCoinFromDec(uatomDenom, sdk.MustNewDecFromStr(highGlobalFeeAmt))} + s.writeGovParamChangeProposalGlobalFees(s.chainA, highGlobalFee) + + // gov proposing new fees + proposalCounter++ + s.T().Logf("Proposal number: %d", proposalCounter) + s.T().Logf("Submitting, deposit and vote legacy Gov Proposal: change global fees empty") + s.submitLegacyGovProposal(chainAAPIEndpoint, submitter, paidFeeAmt+uatomDenom, "param-change", proposalCounter, "/root/.gaia/config/proposal_globalfee.json") + s.depositGovProposal(chainAAPIEndpoint, submitter, paidFeeAmt+uatomDenom, proposalCounter) + s.voteGovProposal(chainAAPIEndpoint, submitter, paidFeeAmt+uatomDenom, proposalCounter, "yes", false) + + // query the proposal status and new fee + s.Require().Eventually( + func() bool { + proposal, err := queryGovProposal(chainAAPIEndpoint, proposalCounter) + s.Require().NoError(err) + return (proposal.GetProposal().Status == govv1beta1.StatusPassed) + }, + 15*time.Second, + 5*time.Second, + ) + + s.Require().Eventually( + func() bool { + globalFees, err := queryGlobalFees(chainAAPIEndpoint) + s.T().Logf("After gov new global fee proposal: %s", globalFees.String()) + s.Require().NoError(err) + + return globalFees.IsEqual(highGlobalFee) + }, + 15*time.Second, + 5*time.Second, + ) + + paidFeeAmt = sdk.MustNewDecFromStr(highGlobalFeeAmt).Mul(sdk.NewDec(gas)).String() + paidFeeAmtHigherMinGasLowerGalobalFee := sdk.MustNewDecFromStr(minGasPrice).Quo(sdk.NewDec(2)).String() + + s.T().Logf("test case: global fee is higher than min_gas_price, globalfee=%s, min_gas_price=%s", globalFees.String(), minGasPrice+uatomDenom) + s.T().Logf("Tx fee is higher than/equal to global fee and min_gas_price, pass") + s.sendMsgSend(s.chainA, 0, submitter, recipient, token.String(), paidFeeAmt+uatomDenom, false) + sucessBankSendCount++ + s.T().Logf("Tx fee is higher than/equal to min_gas_price but lower than global fee, fail") + s.sendMsgSend(s.chainA, 0, submitter, recipient, token.String(), paidFeeAmtHigherMinGasLowerGalobalFee+uatomDenom, true) + + // ---------------------------- test4: global fee with two denoms ----------------------------------- + // prepare gov globalfee proposal + mixGlobalFee := sdk.DecCoins{ + sdk.NewDecCoinFromDec(photonDenom, sdk.NewDec(0)), + sdk.NewDecCoinFromDec(uatomDenom, sdk.MustNewDecFromStr(lowGlobalFeesAmt)), + }.Sort() + s.writeGovParamChangeProposalGlobalFees(s.chainA, mixGlobalFee) + + // gov proposing new fees + proposalCounter++ + s.T().Logf("Proposal number: %d", proposalCounter) + s.T().Logf("Submitting, deposit and vote legacy Gov Proposal: change global fees empty") + s.submitLegacyGovProposal(chainAAPIEndpoint, submitter, paidFeeAmt+uatomDenom, "param-change", proposalCounter, "/root/.gaia/config/proposal_globalfee.json") + s.depositGovProposal(chainAAPIEndpoint, submitter, paidFeeAmt+uatomDenom, proposalCounter) + s.voteGovProposal(chainAAPIEndpoint, submitter, paidFeeAmt+uatomDenom, proposalCounter, "yes", false) + + // query the proposal status and new fee + s.Require().Eventually( + func() bool { + proposal, err := queryGovProposal(chainAAPIEndpoint, proposalCounter) + s.Require().NoError(err) + return (proposal.GetProposal().Status == govv1beta1.StatusPassed) + }, + 15*time.Second, + 5*time.Second, + ) + + s.Require().Eventually( + func() bool { + globalFees, err := queryGlobalFees(chainAAPIEndpoint) + s.T().Logf("After gov new global fee proposal: %s", globalFees.String()) + s.Require().NoError(err) + return globalFees.IsEqual(mixGlobalFee) + }, + 15*time.Second, + 5*time.Second, + ) + + // equal to min_gas_price + paidFeeAmt = sdk.MustNewDecFromStr(minGasPrice).Mul(sdk.NewDec(gas)).String() + paidFeeAmtLow := sdk.MustNewDecFromStr(lowGlobalFeesAmt).Quo(sdk.NewDec(2)).Mul(sdk.NewDec(gas)).String() + + s.T().Logf("test case: global fees contain multiple denoms: one zero coin, one non-zero coin, globalfee=%s, min_gas_price=%s", globalFees.String(), minGasPrice+uatomDenom) + s.T().Logf("Tx with fee higher than/equal to one of denom's amount the global fee, pass") + s.sendMsgSend(s.chainA, 0, submitter, recipient, token.String(), paidFeeAmt+uatomDenom, false) + sucessBankSendCount++ + s.T().Logf("Tx with fee lower than one of denom's amount the global fee, fail") + s.sendMsgSend(s.chainA, 0, submitter, recipient, token.String(), paidFeeAmtLow+uatomDenom, true) + s.T().Logf("Tx with fee empty fee, pass") + s.sendMsgSend(s.chainA, 0, submitter, recipient, token.String(), "", false) + sucessBankSendCount++ + s.T().Logf("Tx with zero coin in the denom of zero coin of global fee, pass") + s.sendMsgSend(s.chainA, 0, submitter, recipient, token.String(), "0"+photonDenom, false) + sucessBankSendCount++ + s.T().Logf("Tx with non-zero coin in the denom of zero coin of global fee, pass") + s.sendMsgSend(s.chainA, 0, submitter, recipient, token.String(), "2"+photonDenom, false) + sucessBankSendCount++ + s.T().Logf("Tx with mulitple fee coins, zero coin and low fee, fail") + s.sendMsgSend(s.chainA, 0, submitter, recipient, token.String(), "0"+photonDenom+","+paidFeeAmtLow+uatomDenom, true) + s.T().Logf("Tx with mulitple fee coins, zero coin and high fee, pass") + s.sendMsgSend(s.chainA, 0, submitter, recipient, token.String(), "0"+photonDenom+","+paidFeeAmt+uatomDenom, false) + sucessBankSendCount++ + s.T().Logf("Tx with mulitple fee coins, all higher than global fee and min_gas_price") + s.sendMsgSend(s.chainA, 0, submitter, recipient, token.String(), "2"+photonDenom+","+paidFeeAmt+uatomDenom, false) + sucessBankSendCount++ + // --------------------------------------------------------------------------- + + // check the balance is correct after previous txs + s.Require().Eventually( + func() bool { + afterRecipientPhotonBalance, err := getSpecificBalance(chainAAPIEndpoint, recipient, photonDenom) + s.Require().NoError(err) + IncrementedPhoton := afterRecipientPhotonBalance.Sub(beforeRecipientPhotonBalance) + photonSent := sdk.NewInt64Coin(photonDenom, sendAmt*int64(sucessBankSendCount)) + return IncrementedPhoton.IsEqual(photonSent) + }, + time.Minute, + 5*time.Second, + ) + + // gov proposing to change back to original global fee + s.T().Logf("Propose to change back to original global fees: %s", initialGlobalFeeAmt+uatomDenom) + oldfees, err := sdk.ParseDecCoins(initialGlobalFeeAmt + uatomDenom) + s.Require().NoError(err) + s.writeGovParamChangeProposalGlobalFees(s.chainA, oldfees) + + proposalCounter++ + s.T().Logf("Proposal number: %d", proposalCounter) + s.T().Logf("Submitting, deposit and vote legacy Gov Proposal: change back global fees") + // fee is 0uatom + s.submitLegacyGovProposal(chainAAPIEndpoint, submitter, paidFeeAmt+photonDenom, "param-change", proposalCounter, "/root/.gaia/config/proposal_globalfee.json") + s.depositGovProposal(chainAAPIEndpoint, submitter, paidFeeAmt+photonDenom, proposalCounter) + s.voteGovProposal(chainAAPIEndpoint, submitter, paidFeeAmt+photonDenom, proposalCounter, "yes", false) + + // query the proposal status and fee + s.Require().Eventually( + func() bool { + proposal, err := queryGovProposal(chainAAPIEndpoint, proposalCounter) + s.Require().NoError(err) + return (proposal.GetProposal().Status == govv1beta1.StatusPassed) + }, + 15*time.Second, + 5*time.Second, + ) + + s.Require().Eventually( + func() bool { + fees, err := queryGlobalFees(chainAAPIEndpoint) + s.T().Logf("After gov proposal to change back global fees: %s", oldfees.String()) + s.Require().NoError(err) + + return fees.IsEqual(oldfees) + }, + 15*time.Second, + 5*time.Second, + ) +} + +func (s *IntegrationTestSuite) TestByPassMinFeeWithdrawReward() { + // time.Sleep(10) + chainAAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chainA.id][0].GetHostPort("1317/tcp")) + paidFeeAmt := sdk.MustNewDecFromStr(minGasPrice).Mul(sdk.NewDec(gas)).String() + + payee, err := s.chainA.validators[0].keyInfo.GetAddress() + s.Require().NoError(err) + // pass + s.T().Logf("bypass-msg with fee in the denom of global fee, pass") + s.withdrawReward(s.chainA, 0, chainAAPIEndpoint, payee.String(), paidFeeAmt+uatomDenom, false) + // pass + s.T().Logf("bypass-msg with zero coin in the denom of global fee, pass") + s.withdrawReward(s.chainA, 0, chainAAPIEndpoint, payee.String(), "0"+uatomDenom, false) + // pass + s.T().Logf("bypass-msg with zero coin not in the denom of global fee, pass") + s.withdrawReward(s.chainA, 0, chainAAPIEndpoint, payee.String(), "0"+photonDenom, false) + // fail + s.T().Logf("bypass-msg with non-zero coin not in the denom of global fee, fail") + s.withdrawReward(s.chainA, 0, chainAAPIEndpoint, payee.String(), paidFeeAmt+photonDenom, true) +} + +// todo add fee test with wrong denom order diff --git a/tests/e2e/e2e_util_test.go b/tests/e2e/e2e_util_test.go index 4fe90dcd38e..76c446027f0 100644 --- a/tests/e2e/e2e_util_test.go +++ b/tests/e2e/e2e_util_test.go @@ -66,7 +66,7 @@ func (s *IntegrationTestSuite) connectIBCChains() { s.T().Logf("connected %s and %s chains via IBC", s.chainA.id, s.chainB.id) } -func (s *IntegrationTestSuite) sendMsgSend(c *chain, valIdx int, from, to, amt, fees string) { +func (s *IntegrationTestSuite) sendMsgSend(c *chain, valIdx int, from, to, amt, fees string, expectErr bool) { ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() @@ -111,13 +111,69 @@ func (s *IntegrationTestSuite) sendMsgSend(c *chain, valIdx int, from, to, amt, var txResp sdk.TxResponse s.Require().NoError(cdc.UnmarshalJSON(outBuf.Bytes(), &txResp)) - endpoint := fmt.Sprintf("http://%s", s.valResources[c.id][valIdx].GetHostPort("1317/tcp")) // wait for the tx to be committed on chain s.Require().Eventuallyf( func() bool { - return queryGaiaTx(endpoint, txResp.TxHash) == nil + gotErr := queryGaiaTx(endpoint, txResp.TxHash) != nil + return gotErr == expectErr + }, + time.Minute, + 5*time.Second, + "stdout: %s, stderr: %s", + outBuf.String(), errBuf.String(), + ) +} + +func (s *IntegrationTestSuite) withdrawReward(c *chain, valIdx int, endpoint, payee, fees string, expectErr bool) { + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + s.T().Logf("%s withdraw-all-rewards on chain %s", payee, c.id) + + exec, err := s.dkrPool.Client.CreateExec(docker.CreateExecOptions{ + Context: ctx, + AttachStdout: true, + AttachStderr: true, + Container: s.valResources[c.id][valIdx].Container.ID, + User: "root", + Cmd: []string{ + "gaiad", + "tx", + "distribution", + "withdraw-all-rewards", + fmt.Sprintf("--%s=%s", flags.FlagFrom, payee), + fmt.Sprintf("--%s=%s", flags.FlagGasPrices, fees), + fmt.Sprintf("--%s=%s", flags.FlagChainID, c.id), + "--keyring-backend=test", + "--output=json", + "-y", + }, + }) + s.Require().NoError(err) + + var ( + outBuf bytes.Buffer + errBuf bytes.Buffer + ) + + err = s.dkrPool.Client.StartExec(exec.ID, docker.StartExecOptions{ + Context: ctx, + Detach: false, + OutputStream: &outBuf, + ErrorStream: &errBuf, + }) + s.Require().NoErrorf(err, "stdout: %s, stderr: %s", outBuf.String(), errBuf.String()) + + var txResp sdk.TxResponse + s.Require().NoError(cdc.UnmarshalJSON(outBuf.Bytes(), &txResp)) + + // wait for the tx to be committed on chain + s.Require().Eventuallyf( + func() bool { + gotErr := queryGaiaTx(endpoint, txResp.TxHash) != nil + return gotErr == expectErr }, time.Minute, 5*time.Second, @@ -349,7 +405,6 @@ func (s *IntegrationTestSuite) executeGaiaTxCommand(ctx context.Context, c *chai ErrorStream: &errBuf, }) s.Require().NoError(err) - s.Require().NoError(cdc.UnmarshalJSON(outBuf.Bytes(), &txResp)) return strings.Contains(txResp.String(), "code: 0") }, diff --git a/tests/e2e/genesis.go b/tests/e2e/genesis.go index c738f043f2e..367c50d6024 100644 --- a/tests/e2e/genesis.go +++ b/tests/e2e/genesis.go @@ -16,6 +16,8 @@ import ( govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" tmtypes "github.com/tendermint/tendermint/types" + + globfeetypes "github.com/cosmos/gaia/v8/x/globalfee/types" ) func getGenDoc(path string) (*tmtypes.GenesisDoc, error) { @@ -42,7 +44,7 @@ func getGenDoc(path string) (*tmtypes.GenesisDoc, error) { return doc, nil } -func addGenesisAccount(path, moniker, amountStr string, accAddr sdk.AccAddress) error { +func modifyGenesis(path, moniker, amountStr string, accAddr sdk.AccAddress, globfees string) error { serverCtx := server.NewDefaultContext() config := serverCtx.Config @@ -103,6 +105,19 @@ func addGenesisAccount(path, moniker, amountStr string, accAddr sdk.AccAddress) } appState[banktypes.ModuleName] = bankGenStateBz + // setup global fee in genesis + globfeeState := globfeetypes.GetGenesisStateFromAppState(cdc, appState) + minGases, err := sdk.ParseDecCoins(globfees) + if err != nil { + return fmt.Errorf("failed to parse fee coins: %w", err) + } + globfeeState.Params.MinimumGasPrices = minGases + globfeeStateBz, err := cdc.MarshalJSON(globfeeState) + if err != nil { + return fmt.Errorf("failed to marshal global fee genesis state: %w", err) + } + appState[globfeetypes.ModuleName] = globfeeStateBz + // Refactor to separate method amnt := math.NewInt(10000) quorum, _ := sdk.NewDecFromStr("0.000000000000000001") @@ -124,7 +139,6 @@ func addGenesisAccount(path, moniker, amountStr string, accAddr sdk.AccAddress) if err != nil { return fmt.Errorf("failed to marshal application genesis state: %w", err) } - genDoc.AppState = appStateJSON return genutil.ExportGenesisFile(genDoc, genFile) } diff --git a/x/globalfee/types/genesis.go b/x/globalfee/types/genesis.go new file mode 100644 index 00000000000..a87d8d9891a --- /dev/null +++ b/x/globalfee/types/genesis.go @@ -0,0 +1,40 @@ +package types + +import ( + "encoding/json" + + "github.com/cosmos/cosmos-sdk/codec" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// NewGenesisState - Create a new genesis state +func NewGenesisState(params Params) *GenesisState { + return &GenesisState{ + Params: params, + } +} + +// DefaultGenesisState - Return a default genesis state +func DefaultGenesisState() *GenesisState { + return NewGenesisState(DefaultParams()) +} + +// GetGenesisStateFromAppState returns x/auth GenesisState given raw application +// genesis state. +func GetGenesisStateFromAppState(cdc codec.Codec, appState map[string]json.RawMessage) *GenesisState { + var genesisState GenesisState + + if appState[ModuleName] != nil { + cdc.MustUnmarshalJSON(appState[ModuleName], &genesisState) + } + + return &genesisState +} + +func ValidateGenesis(data GenesisState) error { + if err := data.Params.ValidateBasic(); err != nil { + return sdkerrors.Wrap(err, "globalfee params") + } + + return nil +}