diff --git a/app/ante.go b/app/ante.go index 657ef1f197..2e0f63df62 100644 --- a/app/ante.go +++ b/app/ante.go @@ -53,6 +53,10 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) { return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "custom akash governance keeper is required for ante builder") } + if options.FeegrantKeeper == nil { + return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "akash feegrant keeper is required for ante builder") + } + anteDecorators := []sdk.AnteDecorator{ ante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first ante.NewRejectExtensionOptionsDecorator(), diff --git a/app/app.go b/app/app.go index 167f2099ac..0fdd05dc75 100644 --- a/app/app.go +++ b/app/app.go @@ -452,6 +452,7 @@ func NewApp( HandlerOptions: ante.HandlerOptions{ AccountKeeper: app.Keepers.Cosmos.Acct, BankKeeper: app.Keepers.Cosmos.Bank, + FeegrantKeeper: app.Keepers.Cosmos.FeeGrant, SignModeHandler: encodingConfig.TxConfig.SignModeHandler(), SigGasConsumer: ante.DefaultSigVerificationGasConsumer, }, diff --git a/make/test-upgrade.mk b/make/test-upgrade.mk index adb54fb709..3f964a1a8f 100644 --- a/make/test-upgrade.mk +++ b/make/test-upgrade.mk @@ -37,7 +37,7 @@ test: $(COSMOVISOR) init -config=test-config.json \ -upgrade-name=$(UPGRADE_TO) \ -upgrade-version="$(UPGRADE_BINARY_VERSION)" \ - -test-cases=upgrade-$(UPGRADE_TO).json + -test-cases=test-cases.json .PHONY: test-reset test-reset: diff --git a/meta.json b/meta.json index a8d22c66e8..8eebba44f9 100644 --- a/meta.json +++ b/meta.json @@ -29,6 +29,11 @@ "skipped": false, "from_binary": "v0.32.3", "from_version": "v0.32.0" + }, + "v0.36.0": { + "skipped": false, + "from_binary": "v0.34.1", + "from_version": "v0.34.0" } } } diff --git a/tests/upgrade/test-cases.json b/tests/upgrade/test-cases.json new file mode 100644 index 0000000000..c7887e704e --- /dev/null +++ b/tests/upgrade/test-cases.json @@ -0,0 +1,58 @@ +{ + "v0.36.0": { + }, + "v0.34.0": { + "migrations": { + } + }, + "v0.32.0": { + "migrations": { + "market": { + "from": "4", + "to": "5" + } + } + }, + "v0.30.0": { + }, + "v0.28.0": { + "migrations": { + "market": { + "from": "3", + "to": "4" + } + } + }, + "v0.26.0": { + "modules": { + "added": [ + ] + }, + "migrations": { + } + }, + "v0.24.0": { + "modules": { + "added": [ + "agov", + "astaking", + "feegrant", + "take" + ] + }, + "migrations": { + "deployment": { + "from": "2", + "to": "3" + }, + "market": { + "from": "2", + "to": "3" + }, + "transfer": { + "from": "1", + "to": "2" + } + } + } +} diff --git a/tests/upgrade/upgrade-v0.24.0.json b/tests/upgrade/upgrade-v0.24.0.json deleted file mode 100644 index 4a42ab0063..0000000000 --- a/tests/upgrade/upgrade-v0.24.0.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "modules": { - "added": [ - "agov", - "astaking", - "feegrant", - "take" - ] - }, - "migrations": { - "deployment": { - "from": "2", - "to": "3" - }, - "market": { - "from": "2", - "to": "3" - }, - "transfer": { - "from": "1", - "to": "2" - } - } -} diff --git a/tests/upgrade/upgrade-v0.26.0.json b/tests/upgrade/upgrade-v0.26.0.json deleted file mode 100644 index 92284be3cd..0000000000 --- a/tests/upgrade/upgrade-v0.26.0.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "modules": { - "added": [ - ] - }, - "migrations": { - } -} diff --git a/tests/upgrade/upgrade-v0.28.0.json b/tests/upgrade/upgrade-v0.28.0.json deleted file mode 100644 index 4eae0ffe42..0000000000 --- a/tests/upgrade/upgrade-v0.28.0.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "migrations": { - "market": { - "from": "3", - "to": "4" - } - } -} diff --git a/tests/upgrade/upgrade-v0.30.0.json b/tests/upgrade/upgrade-v0.30.0.json deleted file mode 100644 index 2c63c08510..0000000000 --- a/tests/upgrade/upgrade-v0.30.0.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} diff --git a/tests/upgrade/upgrade-v0.32.0.json b/tests/upgrade/upgrade-v0.32.0.json deleted file mode 100644 index 12769d3ba3..0000000000 --- a/tests/upgrade/upgrade-v0.32.0.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "migrations": { - "market": { - "from": "4", - "to": "5" - } - } -} diff --git a/tests/upgrade/upgrade-v0.34.0.json b/tests/upgrade/upgrade-v0.34.0.json deleted file mode 100644 index 0a47ef39d8..0000000000 --- a/tests/upgrade/upgrade-v0.34.0.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "migrations": { - } -} diff --git a/tests/upgrade/upgrade_test.go b/tests/upgrade/upgrade_test.go index e94e106c77..01af17d744 100644 --- a/tests/upgrade/upgrade_test.go +++ b/tests/upgrade/upgrade_test.go @@ -161,7 +161,7 @@ type nodeStatus struct { } `json:"SyncInfo"` } -type testCases struct { +type testCase struct { Modules struct { Added []string `json:"added"` Removed []string `json:"removed"` @@ -176,6 +176,8 @@ type testCases struct { } `json:"migrations"` } +type testCases map[string]testCase + type validatorParams struct { home string homedir string @@ -198,7 +200,7 @@ type validator struct { group *errgroup.Group upgradeInfo string params validatorParams - tConfig testCases + tConfig testCase upgradeSuccessful chan struct{} testErrsCh chan []string } @@ -315,9 +317,11 @@ func TestUpgrade(t *testing.T) { require.NoError(t, err) } - var tConfig testCases + var tConfig testCase // load testcases config { + tCases := make(testCases) + tFile, err := os.Open(*testCasesFile) require.NoError(t, err) defer func() { @@ -327,8 +331,12 @@ func TestUpgrade(t *testing.T) { data, err := io.ReadAll(tFile) require.NoError(t, err) - err = json.Unmarshal(data, &tConfig) + err = json.Unmarshal(data, &tCases) require.NoError(t, err) + + var valid bool + tConfig, valid = tCases[*upgradeName] + require.True(t, valid) } cmdr := &commander{} @@ -736,7 +744,7 @@ func (l *upgradeTest) submitUpgradeProposal() error { return nil } -func newValidator(ctx context.Context, t *testing.T, params validatorParams, tConfig testCases) *validator { +func newValidator(ctx context.Context, t *testing.T, params validatorParams, tConfig testCase) *validator { ctx, cancel := context.WithCancel(ctx) group, ctx := errgroup.WithContext(ctx) diff --git a/tests/upgrade/v0.36.0/postupgrade.go b/tests/upgrade/v0.36.0/postupgrade.go new file mode 100644 index 0000000000..5ef3544a5d --- /dev/null +++ b/tests/upgrade/v0.36.0/postupgrade.go @@ -0,0 +1,239 @@ +//go:build e2e.upgrade + +// Package v0_36_0 +// nolint revive +package v0_36_0 + +import ( + "context" + "testing" + "time" + + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/cosmos/cosmos-sdk/x/feegrant" + "github.com/spf13/pflag" + "github.com/stretchr/testify/require" + + sdkclient "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/authz" + "github.com/cosmos/go-bip39" + + cltypes "github.com/akash-network/akash-api/go/node/client/types" + dtypes "github.com/akash-network/akash-api/go/node/deployment/v1beta3" + + "github.com/akash-network/node/app" + "github.com/akash-network/node/client" + "github.com/akash-network/node/cmd/common" + "github.com/akash-network/node/sdl" + uttypes "github.com/akash-network/node/tests/upgrade/types" +) + +const ( + mnemonicEntropySize = 256 +) + +const ( + testSDL = ` +--- +version: "2.0" +services: + web: + image: nginx + expose: + - port: 80 + accept: + - ahostname.com + to: + - global: true + - port: 12345 + to: + - global: true + proto: udp +profiles: + compute: + web: + resources: + cpu: + units: "100m" + memory: + size: "128Mi" + storage: + size: "1Gi" + placement: + westcoast: + attributes: + region: us-west + signedBy: + anyOf: + - 1 + - 2 + allOf: + - 3 + - 4 + pricing: + web: + denom: uakt + amount: 50 +deployment: + web: + westcoast: + profile: web + count: 2 +` +) + +func init() { + uttypes.RegisterPostUpgradeWorker("v0.36.0", &postUpgrade{}) +} + +type postUpgrade struct{} + +var _ uttypes.TestWorker = (*postUpgrade)(nil) + +func (pu *postUpgrade) Run(ctx context.Context, t *testing.T, params uttypes.TestParams) { + encodingConfig := app.MakeEncodingConfig() + + rpcClient, err := sdkclient.NewClientFromNode(params.Node) + require.NoError(t, err) + + cctx := sdkclient.Context{}. + WithCodec(encodingConfig.Marshaler). + WithInterfaceRegistry(encodingConfig.InterfaceRegistry). + WithTxConfig(encodingConfig.TxConfig). + WithLegacyAmino(encodingConfig.Amino). + WithAccountRetriever(authtypes.AccountRetriever{}). + WithBroadcastMode(flags.BroadcastBlock). + WithHomeDir(params.Home). + WithChainID(params.ChainID). + WithNodeURI(params.Node). + WithClient(rpcClient). + WithSkipConfirmation(true). + WithFrom(params.From). + WithKeyringDir(params.Home) + + kr, err := sdkclient.NewKeyringFromBackend(cctx, params.KeyringBackend) + require.NoError(t, err) + + cctx = cctx.WithKeyring(kr) + + info, err := kr.Key(params.From) + require.NoError(t, err) + + entropySeed, err := bip39.NewEntropy(mnemonicEntropySize) + require.NoError(t, err) + + mnemonic, err := bip39.NewMnemonic(entropySeed) + require.NoError(t, err) + + keyringAlgos, _ := kr.SupportedAlgorithms() + + algo, err := keyring.NewSigningAlgoFromString(string(hd.Secp256k1Type), keyringAlgos) + + coinType := sdk.GetConfig().GetCoinType() + hdPath := hd.CreateHDPath(coinType, 0, 0).String() + + testAcc, err := kr.NewAccount("depl", mnemonic, "", hdPath, algo) + require.NoError(t, err) + + mainCctx := cctx.WithFromName(info.GetName()). + WithFromAddress(info.GetAddress()) + + testCctx := cctx.WithFromName(testAcc.GetName()). + WithFromAddress(testAcc.GetAddress()). + WithFeeGranterAddress(info.GetAddress()) + + opts := []cltypes.ClientOption{ + cltypes.WithGasPrices("0.025uakt"), + cltypes.WithGas(flags.GasSetting{Simulate: false, Gas: 1000000}), + cltypes.WithGasAdjustment(2), + } + + mcl, err := client.DiscoverClient(ctx, mainCctx, opts...) + require.NoError(t, err) + require.NotNil(t, mcl) + + basic := &feegrant.BasicAllowance{ + SpendLimit: sdk.Coins{sdk.NewCoin("uakt", sdk.NewInt(500000))}, + } + + fmsg, err := feegrant.NewMsgGrantAllowance(basic, info.GetAddress(), testAcc.GetAddress()) + require.NoError(t, err) + + // give test key deployment deposit authorization + spendLimit := sdk.NewCoin("uakt", sdk.NewInt(10000000)) + authorization := dtypes.NewDepositDeploymentAuthorization(spendLimit) + dmsg, err := authz.NewMsgGrant(info.GetAddress(), testAcc.GetAddress(), authorization, time.Now().AddDate(1, 0, 0)) + + msgs := []sdk.Msg{ + fmsg, + dmsg, + } + + // authorize test account with feegrant + resp, err := mcl.Tx().Broadcast(ctx, msgs) + require.NoError(t, err) + require.NotNil(t, resp) + require.IsType(t, &sdk.TxResponse{}, resp) + txResp := resp.(*sdk.TxResponse) + require.Equal(t, uint32(0), txResp.Code) + + dcl, err := client.DiscoverClient(ctx, testCctx, opts...) + require.NoError(t, err) + require.NotNil(t, mcl) + + tsdl, err := sdl.Read([]byte(testSDL)) + require.NoError(t, err) + require.NotNil(t, tsdl) + + syncInfo, err := dcl.Node().SyncInfo(ctx) + require.NoError(t, err) + require.NotNil(t, syncInfo) + require.False(t, syncInfo.CatchingUp) + + dID := dtypes.DeploymentID{ + Owner: testAcc.GetAddress().String(), + DSeq: uint64(syncInfo.LatestBlockHeight), + } + + dVersion, err := tsdl.Version() + require.NoError(t, err) + + dGroups, err := tsdl.DeploymentGroups() + require.NoError(t, err) + + deposit, err := common.DetectDeposit(ctx, &pflag.FlagSet{}, dcl.Query(), "deployment", "MinDeposits") + require.NoError(t, err) + + qresp, err := dcl.Query().Bank().Balance(ctx, &banktypes.QueryBalanceRequest{ + Denom: "uakt", + Address: testAcc.GetAddress().String(), + }) + require.NoError(t, err) + require.True(t, qresp.Balance.IsZero()) + + // create deployment with deposit with both fee&deposit grants + // should not have any errors + deploymentMsg := &dtypes.MsgCreateDeployment{ + ID: dID, + Version: dVersion, + Groups: make([]dtypes.GroupSpec, 0, len(dGroups)), + Deposit: deposit, + Depositor: info.GetAddress().String(), + } + + for _, group := range dGroups { + deploymentMsg.Groups = append(deploymentMsg.Groups, *group) + } + + resp, err = dcl.Tx().Broadcast(ctx, []sdk.Msg{deploymentMsg}) + require.NoError(t, err) + require.NotNil(t, resp) + require.IsType(t, &sdk.TxResponse{}, resp) + txResp = resp.(*sdk.TxResponse) + require.Equal(t, uint32(0), txResp.Code) +} diff --git a/tests/upgrade/workers_test.go b/tests/upgrade/workers_test.go index ba590ac5b4..babb166567 100644 --- a/tests/upgrade/workers_test.go +++ b/tests/upgrade/workers_test.go @@ -6,4 +6,5 @@ import ( _ "github.com/akash-network/node/tests/upgrade/v0.26.0" _ "github.com/akash-network/node/tests/upgrade/v0.32.0" _ "github.com/akash-network/node/tests/upgrade/v0.34.0" + _ "github.com/akash-network/node/tests/upgrade/v0.36.0" ) diff --git a/upgrades/CHANGELOG.md b/upgrades/CHANGELOG.md index d6af2f3120..c81ba3850b 100644 --- a/upgrades/CHANGELOG.md +++ b/upgrades/CHANGELOG.md @@ -43,6 +43,10 @@ Goal of the upgrade here Add new upgrades after this line based on the template above ----- +##### v0.36.0 + +1. Init Feegrant Keeper reference for `NewDeductFeeDecorator`. Fixes issue with feegrant enabled but not actually working due to uninitialized reference in Ante config + ##### v0.34.0 1. Extend authz implementation for DeploymentDeposit to allow grantee re-use of unspent funds. diff --git a/upgrades/software/v0.36.0/init.go b/upgrades/software/v0.36.0/init.go new file mode 100644 index 0000000000..da505525a7 --- /dev/null +++ b/upgrades/software/v0.36.0/init.go @@ -0,0 +1,11 @@ +// Package v0_36_0 +// nolint revive +package v0_36_0 + +import ( + utypes "github.com/akash-network/node/upgrades/types" +) + +func init() { + utypes.RegisterUpgrade(UpgradeName, initUpgrade) +} diff --git a/upgrades/software/v0.36.0/upgrade.go b/upgrades/software/v0.36.0/upgrade.go new file mode 100644 index 0000000000..7a342587da --- /dev/null +++ b/upgrades/software/v0.36.0/upgrade.go @@ -0,0 +1,47 @@ +// Package v0_36_0 +// nolint revive +package v0_36_0 + +import ( + "fmt" + + "github.com/tendermint/tendermint/libs/log" + + storetypes "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + + apptypes "github.com/akash-network/node/app/types" + utypes "github.com/akash-network/node/upgrades/types" +) + +const ( + UpgradeName = "v0.36.0" +) + +type upgrade struct { + *apptypes.App + log log.Logger +} + +var _ utypes.IUpgrade = (*upgrade)(nil) + +func initUpgrade(log log.Logger, app *apptypes.App) (utypes.IUpgrade, error) { + up := &upgrade{ + App: app, + log: log.With("module", fmt.Sprintf("upgrade/%s", UpgradeName)), + } + + return up, nil +} + +func (up *upgrade) StoreLoader() *storetypes.StoreUpgrades { + return &storetypes.StoreUpgrades{} +} + +func (up *upgrade) UpgradeHandler() upgradetypes.UpgradeHandler { + return func(ctx sdk.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { + return up.MM.RunMigrations(ctx, up.Configurator, fromVM) + } +} diff --git a/upgrades/upgrades.go b/upgrades/upgrades.go index c999c9713b..4595db5ae4 100644 --- a/upgrades/upgrades.go +++ b/upgrades/upgrades.go @@ -1,6 +1,8 @@ package upgrades import ( + // nolint: revive + _ "github.com/akash-network/node/upgrades/software/v0.36.0" // nolint: revive _ "github.com/akash-network/node/upgrades/software/v0.34.0" // nolint: revive