From aa2b01e7ee24aecc011d9bdb655ed5945016f9ca Mon Sep 17 00:00:00 2001 From: Mikhail Kornilov Date: Thu, 5 Nov 2020 04:45:21 -0800 Subject: [PATCH] [Master][DFI-928] Mainnet v1.0 migration (#235) * [DFI-929] migration to v1.0 added; MaxSelfStake staking param support added * [DFI-929] fixed CSDK version * [DFI-928] BaseMigrate -> Migrate renaming * [DFI-929] defaults and restrictions modified to match v1.0 release * [DFI-947] CSDK version bump * [DFI-929] appState export update to support zero-height genesis export * [DFI-929] multisig, orderbook mods: PrepareForZeroHeight squash funcs added * [DFI-929] multisig mod: call queue fix for genesis squash; app export refactoring, debug added * [DFI-929] ccstorage, vmauth mods: PrepareForZeroHeight added; mainnet export config added * [DFI-929] mint mod PrepareForZeroHeight support added * [DFI-929] gov mod PrepareForZeroHeight support added * [DFI-947] Mainnet v1.0 migration fixes and report generation * [DFI-947] Debug validator disabled * [DFI-947] Mainnet v1.0 export report modification to support a newer CSDK version (BankRewards per validator) * Linter fixes; tests skip due to changed app limitation; simulator fix to support new distr RewardsBank API * CLItester fix: increased init acc balance as Gov deposit increased) * CSDK version bump --- app/app.go | 19 - app/cli_test.go | 4 + app/common_test.go | 2 + app/export.go | 307 ++++++++ app/export_v10.go | 729 ++++++++++++++++++ app/integ_test.go | 4 +- app/rest_test.go | 2 + app/unit_distribution_test.go | 1 + .../genesis/defaults/common_defaults.go | 11 +- cmd/config/genesis/genesis.go | 1 + cmd/config/restrictions/restrictions.go | 19 +- go.mod | 2 +- go.sum | 30 +- helpers/tests/clitester/cli_tester_configs.go | 2 +- .../simulator/sim_ops_rewards_delegator.go | 2 +- x/ccstorage/alias.go | 4 + x/ccstorage/internal/keeper/squash.go | 50 ++ x/currencies/internal/keeper/genesis.go | 2 +- x/currencies/internal/keeper/genesis_test.go | 8 +- x/currencies/internal/keeper/issue.go | 26 +- .../internal/migrations/v0_7/migration.go | 38 - .../internal/migrations/v1_0/migration.go | 71 ++ x/migration/internal/types/migration.go | 4 +- x/multisig/internal/keeper/squash.go | 25 + x/orderbook/internal/keeper/squash.go | 35 + x/vm/client/cli/tx.go | 2 +- x/vmauth/alias.go | 4 + x/vmauth/internal/keeper/squash.go | 173 +++++ 28 files changed, 1451 insertions(+), 126 deletions(-) create mode 100644 app/export.go create mode 100644 app/export_v10.go create mode 100644 x/ccstorage/internal/keeper/squash.go delete mode 100644 x/migration/internal/migrations/v0_7/migration.go create mode 100644 x/migration/internal/migrations/v1_0/migration.go create mode 100644 x/multisig/internal/keeper/squash.go create mode 100644 x/orderbook/internal/keeper/squash.go create mode 100644 x/vmauth/internal/keeper/squash.go diff --git a/app/app.go b/app/app.go index 92693da2..748f3b12 100644 --- a/app/app.go +++ b/app/app.go @@ -31,7 +31,6 @@ import ( abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/libs/log" tmOs "github.com/tendermint/tendermint/libs/os" - tmTypes "github.com/tendermint/tendermint/types" dbm "github.com/tendermint/tm-db" "google.golang.org/grpc" @@ -619,21 +618,3 @@ func (app *DnServiceApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) a func (app *DnServiceApp) LoadHeight(height int64) error { return app.LoadVersion(height, app.keys[bam.MainStoreKey]) } - -// Exports genesis and validators. -func (app *DnServiceApp) ExportAppStateAndValidators(forZeroHeight bool, jailWhiteList []string, -) (appState json.RawMessage, validators []tmTypes.GenesisValidator, err error) { - - // as if they could withdraw from the start of the next block. - ctx := app.NewContext(true, abci.Header{Height: app.LastBlockHeight()}) - - genState := app.mm.ExportGenesis(ctx) - appState, err = codec.MarshalJSONIndent(app.cdc, genState) - if err != nil { - return nil, nil, err - } - - validators = staking.WriteValidators(ctx, app.stakingKeeper) - - return appState, validators, nil -} diff --git a/app/cli_test.go b/app/cli_test.go index 7afdd057..c189314b 100644 --- a/app/cli_test.go +++ b/app/cli_test.go @@ -32,6 +32,7 @@ const ( // TestBankSXFI_CLI transfers for sxfi token must be disallowed func TestBankSXFI_CLI(t *testing.T) { + t.Skip("skipped as dist limitations are disabled for the Mainnet") t.Parallel() ct := cliTester.New(t, false) @@ -56,6 +57,7 @@ func TestBankSXFI_CLI(t *testing.T) { // TestGovSXFI_CLI gov deposit allowed just for sxfi token func TestGovSXFI_CLI(t *testing.T) { + t.Skip("test skipped as it is no longer relevant for Mainnet") t.Parallel() ct := cliTester.New(t, false) @@ -71,6 +73,7 @@ func TestGovSXFI_CLI(t *testing.T) { // TestStakeSXFI_CLI staking allowed just for sxfi token func TestStakeSXFI_CLI(t *testing.T) { + t.Skip("skipped as dist limitations are disabled for the Mainnet") t.Parallel() ct := cliTester.New(t, false) @@ -305,6 +308,7 @@ func TestCurrencies_CLI(t *testing.T) { // Check that distribution commands in CLI disabled. func TestDisableRewards_CLI(t *testing.T) { + t.Skip("skipped as dist limitations are disabled for the Mainnet") t.Parallel() ct := cliTester.New(t, false) diff --git a/app/common_test.go b/app/common_test.go index 186936a6..3d641dee 100644 --- a/app/common_test.go +++ b/app/common_test.go @@ -374,6 +374,8 @@ func GetGenesis(app *DnServiceApp, chainID, monikerID string, nodeAccPrivKey sec stakingGenesis := staking.GenesisState{} app.cdc.MustUnmarshalJSON(genesisState[staking.ModuleName], &stakingGenesis) stakingGenesis.Params.BondDenom = defaults.MainDenom + maxStakingLvl, _ := sdk.NewIntFromString("1000000000000000000000000") + stakingGenesis.Params.MaxSelfDelegationLvl = maxStakingLvl genesisState[staking.ModuleName] = codec.MustMarshalJSONIndent(app.cdc, stakingGenesis) // update mint denom diff --git a/app/export.go b/app/export.go new file mode 100644 index 00000000..307e203a --- /dev/null +++ b/app/export.go @@ -0,0 +1,307 @@ +package app + +import ( + "encoding/json" + "fmt" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/distribution" + "github.com/cosmos/cosmos-sdk/x/gov" + "github.com/cosmos/cosmos-sdk/x/mint" + "github.com/cosmos/cosmos-sdk/x/slashing" + "github.com/cosmos/cosmos-sdk/x/staking" + "github.com/cosmos/cosmos-sdk/x/supply" + abci "github.com/tendermint/tendermint/abci/types" + tmTypes "github.com/tendermint/tendermint/types" + + "github.com/dfinance/dnode/x/ccstorage" + "github.com/dfinance/dnode/x/multisig" + "github.com/dfinance/dnode/x/orderbook" + "github.com/dfinance/dnode/x/vmauth" +) + +// Exports genesis and validators. +func (app *DnServiceApp) ExportAppStateAndValidators(forZeroHeight bool, jailWhiteList []string, +) (appState json.RawMessage, validators []tmTypes.GenesisValidator, retErr error) { + + var err error + + // create a new context + ctx := app.NewContext(true, abci.Header{Height: app.LastBlockHeight()}) + + // zero-height squash + if forZeroHeight { + if err := app.prepareGenesisForZeroHeight(ctx, jailWhiteList); err != nil { + retErr = fmt.Errorf("preparing genesis for zero-height: %w", err) + return + } + } + + // genesis export + genState := app.mm.ExportGenesis(ctx) + appState, err = codec.MarshalJSONIndent(app.cdc, genState) + if err != nil { + retErr = fmt.Errorf("genState JSON marshal: %w", err) + return + } + + validators = staking.WriteValidators(ctx, app.stakingKeeper) + + return appState, validators, nil +} + +func (app *DnServiceApp) checkInvariants(ctx sdk.Context) error { + for _, invRoute := range app.crisisKeeper.Routes() { + res, stop := invRoute.Invar(ctx) + if stop { + return fmt.Errorf("module %s (%s): %s", invRoute.ModuleName, invRoute.Route, res) + } + } + + return nil +} + +// prepareGenesisForZeroHeight updates current context to fit zero-height genesis. +// Basically it "squashes" all height-dependent storage objects. +func (app *DnServiceApp) prepareGenesisForZeroHeight(ctx sdk.Context, jailWhiteList []string) error { + // Check invariants before + if err := app.checkInvariants(ctx); err != nil { + return fmt.Errorf("pre invariants check failed: %w", err) + } + + // Prepare PrepareForZeroHeight module functions options + optsMap, err := prepareDefaultZeroHeightOptions(jailWhiteList) + if err != nil { + return fmt.Errorf("prepareDefaultZeroHeightOptions: %w", err) + } + //optsMap, err = setDebugZeroHeightOptions(optsMap) + //if err != nil { + // return fmt.Errorf("setDebugZeroHeightOptions: %w", err) + //} + //optsMap, err = setMainnetZeroHeightOptionsV10(optsMap) + //if err != nil { + // return fmt.Errorf("setMainnetZeroHeightOptionsV10: %w", err) + //} + + // CCStorage + { + moduleName := ccstorage.ModuleName + opts := optsMap[moduleName].(ccstorage.SquashOptions) + if err := app.ccsKeeper.PrepareForZeroHeight(ctx, opts); err != nil { + return fmt.Errorf("module %s: %w", moduleName, err) + } + } + // Supply + { + moduleName := supply.ModuleName + opts := optsMap[moduleName].(supply.SquashOptions) + if err := app.supplyKeeper.PrepareForZeroHeight(ctx, opts); err != nil { + return fmt.Errorf("module %s: %w", moduleName, err) + } + } + // VMAuth + { + moduleName := vmauth.ModuleName + opts := optsMap[moduleName].(vmauth.SquashOptions) + if err := app.accountKeeper.PrepareForZeroHeight(ctx, opts); err != nil { + return fmt.Errorf("module %s: %w", moduleName, err) + } + } + // Staking + { + moduleName := staking.ModuleName + opts := optsMap[moduleName].(staking.SquashOptions) + if err := app.stakingKeeper.PrepareForZeroHeight(ctx, opts); err != nil { + return fmt.Errorf("module %s: %w", moduleName, err) + } + } + // Distribution + { + moduleName := distribution.ModuleName + opts := optsMap[moduleName].(distribution.SquashOptions) + if err := app.distrKeeper.PrepareForZeroHeight(ctx, opts); err != nil { + return fmt.Errorf("module %s: %w", moduleName, err) + } + } + // Slashing + { + moduleName := slashing.ModuleName + if err := app.slashingKeeper.PrepareForZeroHeight(ctx); err != nil { + return fmt.Errorf("module %s: %w", moduleName, err) + } + } + // Mint + { + moduleName := mint.ModuleName + opts := optsMap[moduleName].(mint.SquashOptions) + if err := app.mintKeeper.PrepareForZeroHeight(ctx, opts); err != nil { + return fmt.Errorf("module %s: %w", moduleName, err) + } + } + // Gov + { + moduleName := gov.ModuleName + opts := optsMap[moduleName].(gov.SquashOptions) + if err := app.govKeeper.PrepareForZeroHeight(ctx, opts); err != nil { + return fmt.Errorf("module %s: %w", moduleName, err) + } + } + // MultiSig + { + moduleName := multisig.ModuleName + if err := app.msKeeper.PrepareForZeroHeight(ctx); err != nil { + return fmt.Errorf("module %s: %w", moduleName, err) + } + } + // OrderBook + { + moduleName := orderbook.ModuleName + if err := app.orderBookKeeper.PrepareForZeroHeight(ctx); err != nil { + return fmt.Errorf("module %s: %w", moduleName, err) + } + } + + // Check invariants after + if err := app.checkInvariants(ctx); err != nil { + return fmt.Errorf("post invariants check failed: %w", err) + } + + // + if err := app.processMainnetSXFIBalance(ctx); err != nil { + return fmt.Errorf("mainnet v1.0 processing: %w", err) + } + + return nil +} + +// prepareDefaultZeroHeightOptions returns base (default) options map per module for PrepareForZeroHeight functions. +func prepareDefaultZeroHeightOptions(jailWhiteList []string) (map[string]interface{}, error) { + optsMap := make(map[string]interface{}) + + // CCStorage + { + moduleName := ccstorage.ModuleName + opts := ccstorage.NewEmptySquashOptions() + optsMap[moduleName] = opts + } + // Supply + { + moduleName := supply.ModuleName + opts := supply.NewEmptySquashOptions() + optsMap[moduleName] = opts + } + // VMAuth + { + moduleName := vmauth.ModuleName + opts := vmauth.NewEmptySquashOptions() + optsMap[moduleName] = opts + } + // Staking + { + moduleName := staking.ModuleName + opts := staking.NewEmptySquashOptions() + if err := opts.SetJailWhitelistSquashOption(jailWhiteList); err != nil { + return nil, fmt.Errorf("module %s: %w", moduleName, err) + } + optsMap[moduleName] = opts + } + // Distribution + { + moduleName := distribution.ModuleName + opts := distribution.NewEmptySquashOptions() + optsMap[moduleName] = opts + } + // Mint + { + moduleName := mint.ModuleName + opts := mint.NewEmptySquashOptions() + optsMap[moduleName] = opts + } + // Gov + { + moduleName := gov.ModuleName + opts := gov.NewEmptySquashOptions() + optsMap[moduleName] = opts + } + + return optsMap, nil +} + +// setDebugZeroHeightOptions updates options map per module for debug purposes. +// Adds a fake validator jailing all the others. +// This mod is helpful to run exported genesis locally with one up and running validator. +func setDebugZeroHeightOptions(optsMap map[string]interface{}) (map[string]interface{}, error) { + const ( + // Values below are hardcoded according to bootstrap init_single_w_genesis.sh script values + fakeValOperatorAddress = "wallet17raernuazufad6q48uc5jdnqmuzsep5a03dc0n" + fakeValMoniker = "fakeVal" + fakeValPubKey = "walletvalconspub1zcjduepqu9mgrhdjfmwwalv86vdsavvvxfy8r4fmt4py8ehep252rs0acs5q93t5nm" + fakeValSelfDelegationAmount = "1000000000000000000000000" + // + stakingDenom = "sxfi" + ) + + // Supply + { + moduleName := supply.ModuleName + optsObj, found := optsMap[moduleName] + if !found { + return nil, fmt.Errorf("module %s: options not found", moduleName) + } + opts, ok := optsObj.(supply.SquashOptions) + if !ok { + return nil, fmt.Errorf("module %s: options type assert failed: %T", moduleName, optsObj) + } + + if err := opts.SetDenomOp(stakingDenom, false, "", fakeValSelfDelegationAmount); err != nil { + return nil, fmt.Errorf("module %s: %w", moduleName, err) + } + optsMap[moduleName] = opts + } + // VMAuth + { + moduleName := vmauth.ModuleName + optsObj, found := optsMap[moduleName] + if !found { + return nil, fmt.Errorf("module %s: options not found", moduleName) + } + opts, ok := optsObj.(vmauth.SquashOptions) + if !ok { + return nil, fmt.Errorf("module %s: options type assert failed: %T", moduleName, optsObj) + } + + if err := opts.SetAddAccountOp(fakeValOperatorAddress, fakeValSelfDelegationAmount+stakingDenom); err != nil { + return nil, fmt.Errorf("module %s: %w", moduleName, err) + } + optsMap[moduleName] = opts + } + // Staking + { + moduleName := staking.ModuleName + optsObj, found := optsMap[moduleName] + if !found { + return nil, fmt.Errorf("module %s: options not found", moduleName) + } + opts, ok := optsObj.(staking.SquashOptions) + if !ok { + return nil, fmt.Errorf("module %s: options type assert failed: %T", moduleName, optsObj) + } + + accAddr, err := sdk.AccAddressFromBech32(fakeValOperatorAddress) + if err != nil { + return nil, fmt.Errorf("module %s: invalid fakeValOperatorAddress (%s): %w", moduleName, fakeValOperatorAddress, err) + } + valAddr := sdk.ValAddress(accAddr) + + if err := opts.SetAddValidatorOp(fakeValOperatorAddress, fakeValMoniker, fakeValPubKey, fakeValSelfDelegationAmount); err != nil { + return nil, fmt.Errorf("module %s: %w", moduleName, err) + } + if err := opts.SetJailWhitelistSquashOption([]string{valAddr.String()}); err != nil { + return nil, fmt.Errorf("module %s: %w", moduleName, err) + } + optsMap[moduleName] = opts + } + + return optsMap, nil +} diff --git a/app/export_v10.go b/app/export_v10.go new file mode 100644 index 00000000..38e63a14 --- /dev/null +++ b/app/export_v10.go @@ -0,0 +1,729 @@ +package app + +import ( + "encoding/csv" + "encoding/json" + "fmt" + "io" + "os" + "sort" + "strings" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/distribution" + "github.com/cosmos/cosmos-sdk/x/gov" + "github.com/cosmos/cosmos-sdk/x/mint" + "github.com/cosmos/cosmos-sdk/x/staking" + "github.com/cosmos/cosmos-sdk/x/staking/exported" + "github.com/cosmos/cosmos-sdk/x/supply" + + "github.com/dfinance/dnode/cmd/config/genesis/defaults" + "github.com/dfinance/dnode/helpers" + "github.com/dfinance/dnode/x/ccstorage" + "github.com/dfinance/dnode/x/vmauth" +) + +// setMainnetZeroHeightOptionsV10 updates options map per module for Testnet v0.7 -> Mainnet v1.0 migration. +// Options removes all XFI tokens and renames SXFI -> XFI. +func setMainnetZeroHeightOptionsV10(optsMap map[string]interface{}) (map[string]interface{}, error) { + const ( + oldStakingDenom = "sxfi" + newStakingDenom = "xfi" + ) + var ( + denomsToRemove = []string{"xfi", "usdt", "btc"} + ) + + // Supply + { + moduleName := supply.ModuleName + optsObj, found := optsMap[moduleName] + if !found { + return nil, fmt.Errorf("module %s: options not found", moduleName) + } + opts, ok := optsObj.(supply.SquashOptions) + if !ok { + return nil, fmt.Errorf("module %s: options type assert failed: %T", moduleName, optsObj) + } + + for _, denom := range denomsToRemove { + if err := opts.SetDenomOp(denom, true, "", "0"); err != nil { + return nil, fmt.Errorf("module %s: %w", moduleName, err) + } + } + if err := opts.SetDenomOp(oldStakingDenom, false, newStakingDenom, "0"); err != nil { + return nil, fmt.Errorf("module %s: %w", moduleName, err) + } + optsMap[moduleName] = opts + } + // VMAuth + { + moduleName := vmauth.ModuleName + optsObj, found := optsMap[moduleName] + if !found { + return nil, fmt.Errorf("module %s: options not found", moduleName) + } + opts, ok := optsObj.(vmauth.SquashOptions) + if !ok { + return nil, fmt.Errorf("module %s: options type assert failed: %T", moduleName, optsObj) + } + + for _, denom := range denomsToRemove { + if err := opts.SetAccountBalanceOp(denom, true, ""); err != nil { + return nil, fmt.Errorf("module %s: %w", moduleName, err) + } + } + if err := opts.SetAccountBalanceOp(oldStakingDenom, false, newStakingDenom); err != nil { + return nil, fmt.Errorf("module %s: %w", moduleName, err) + } + optsMap[moduleName] = opts + } + // Staking + { + moduleName := staking.ModuleName + optsObj, found := optsMap[moduleName] + if !found { + return nil, fmt.Errorf("module %s: options not found", moduleName) + } + opts, ok := optsObj.(staking.SquashOptions) + if !ok { + return nil, fmt.Errorf("module %s: options type assert failed: %T", moduleName, optsObj) + } + + if err := opts.SetParamsOp(newStakingDenom); err != nil { + return nil, fmt.Errorf("module %s: %w", moduleName, err) + } + optsMap[moduleName] = opts + } + // Distribution + { + moduleName := distribution.ModuleName + optsObj, found := optsMap[moduleName] + if !found { + return nil, fmt.Errorf("module %s: options not found", moduleName) + } + opts, ok := optsObj.(distribution.SquashOptions) + if !ok { + return nil, fmt.Errorf("module %s: options type assert failed: %T", moduleName, optsObj) + } + + if err := opts.SetDecCoinOp(newStakingDenom, true, ""); err != nil { + return nil, fmt.Errorf("module %s: %w", moduleName, err) + } + if err := opts.SetDecCoinOp(oldStakingDenom, false, newStakingDenom); err != nil { + return nil, fmt.Errorf("module %s: %w", moduleName, err) + } + optsMap[moduleName] = opts + } + // Mint + { + moduleName := mint.ModuleName + optsObj, found := optsMap[moduleName] + if !found { + return nil, fmt.Errorf("module %s: options not found", moduleName) + } + opts, ok := optsObj.(mint.SquashOptions) + if !ok { + return nil, fmt.Errorf("module %s: options type assert failed: %T", moduleName, optsObj) + } + + if err := opts.SetParamsOp(newStakingDenom); err != nil { + return nil, fmt.Errorf("module %s: %w", moduleName, err) + } + optsMap[moduleName] = opts + } + // Gov + { + moduleName := gov.ModuleName + optsObj, found := optsMap[moduleName] + if !found { + return nil, fmt.Errorf("module %s: options not found", moduleName) + } + opts, ok := optsObj.(gov.SquashOptions) + if !ok { + return nil, fmt.Errorf("module %s: options type assert failed: %T", moduleName, optsObj) + } + + if err := opts.SetParamsOp(defaults.GovMinDepositAmount + newStakingDenom); err != nil { + return nil, fmt.Errorf("module %s: %w", moduleName, err) + } + optsMap[moduleName] = opts + } + // CCStorage + { + moduleName := ccstorage.ModuleName + optsObj, found := optsMap[moduleName] + if !found { + return nil, fmt.Errorf("module %s: options not found", moduleName) + } + opts, ok := optsObj.(ccstorage.SquashOptions) + if !ok { + return nil, fmt.Errorf("module %s: options type assert failed: %T", moduleName, optsObj) + } + + if err := opts.SetSupplyOperation(true); err != nil { + return nil, fmt.Errorf("module %s: %w", moduleName, err) + } + optsMap[moduleName] = opts + } + + return optsMap, nil +} + +// SXFIBalanceReportItem keeps initial, staked and reward balances per account. +type SXFIBalanceReportItem struct { + AccAddress sdk.AccAddress + AccBalance sdk.Coins + IssueCoins sdk.Coins + RewardCoins sdk.Coins + DelBondingShares sdk.Dec + DelLPShares sdk.Dec + DelBondingTokens sdk.Dec + DelLPTokens sdk.Dec + GenCoins sdk.Coins + StakerReport *SXFIStakerReportItem + IssueBondingDenom string + IssueLPDenom string + BondingDenom string + LPDenom string +} + +// SXFIStakerReportItem is a parsed Staker CSV-report. +type SXFIStakerReportItem struct { + TxHash string + AccAddress sdk.AccAddress + EthAddress string + BondingAmount sdk.Int + LPAmount sdk.Int +} + +// GetInitialBondingBalance returns initial amount for BondingDenom (gen balance + issues). +func (i SXFIBalanceReportItem) GetInitialBondingBalance() sdk.Int { + genAmt := i.GenCoins.AmountOf(i.BondingDenom) + issuedAmt := i.IssueCoins.AmountOf(i.IssueBondingDenom) + if i.StakerReport == nil { + issuedAmt = sdk.ZeroInt() + } + + return genAmt.Add(issuedAmt) +} + +// GetIssueBondingBalance returns initial amount for LPDenom (gen balance + issues). +func (i SXFIBalanceReportItem) GetInitialLPBalance() sdk.Int { + genAmt := i.GenCoins.AmountOf(i.LPDenom) + issuedAmt := i.IssueCoins.AmountOf(i.IssueLPDenom) + if i.StakerReport == nil { + issuedAmt = sdk.ZeroInt() + } + + return genAmt.Add(issuedAmt) +} + +// GetCurrentBondingBalance returns final amount for BondingDenom (current balance + rewards + delegations). +func (i SXFIBalanceReportItem) GetCurrentBondingBalance() sdk.Int { + accBalanceAmt := i.AccBalance.AmountOf(i.BondingDenom) + rewardAmt := i.RewardCoins.AmountOf(i.BondingDenom) + delAmt := i.DelBondingTokens.TruncateInt() + + return accBalanceAmt.Add(rewardAmt).Add(delAmt) +} + +// GetCurrentLPBalance returns final amount for LPDenom (current balance + rewards + delegations). +func (i SXFIBalanceReportItem) GetCurrentLPBalance() sdk.Int { + accBalanceAmt := i.AccBalance.AmountOf(i.LPDenom) + rewardAmt := i.RewardCoins.AmountOf(i.LPDenom) + delAmt := i.DelLPTokens.TruncateInt() + + return accBalanceAmt.Add(rewardAmt).Add(delAmt) +} + +func NewSXFIBalanceReportItem(accAddr sdk.AccAddress, accCoins sdk.Coins, issueBondingDenom, issueLPDenom, bondingDenom, lpDenom string) *SXFIBalanceReportItem { + return &SXFIBalanceReportItem{ + AccAddress: accAddr, + AccBalance: accCoins, + IssueCoins: sdk.NewCoins(), + RewardCoins: sdk.NewCoins(), + DelBondingShares: sdk.ZeroDec(), + DelLPShares: sdk.ZeroDec(), + DelBondingTokens: sdk.ZeroDec(), + DelLPTokens: sdk.ZeroDec(), + GenCoins: sdk.NewCoins(), + StakerReport: nil, + IssueBondingDenom: issueBondingDenom, + IssueLPDenom: issueLPDenom, + BondingDenom: bondingDenom, + LPDenom: lpDenom, + } +} + +type SXFIBalanceReportResult struct { + ReportItem SXFIBalanceReportItem + BondingDiff sdk.Int + LPDiff sdk.Int +} + +type SXFIBalanceReportResults []SXFIBalanceReportResult + +func (results SXFIBalanceReportResults) SaveToCSV(path string) error { + f, err := os.Create(path) + if err != nil { + return fmt.Errorf("creating file: %w", err) + } + defer f.Close() + csvWriter := csv.NewWriter(f) + + // Header + err = csvWriter.Write([]string{ + "AccAddress", + "GenCoins", + "IssueCoins", + "WalletCoins", + "RewardCoins", + "DelBondingTokens", + "DelLPTokens", + "BondingDiff", + "LPDiff", + }) + if err != nil { + return fmt.Errorf("header write: %w", err) + } + + // Entries + for i, result := range results { + err := csvWriter.Write([]string{ + result.ReportItem.AccAddress.String(), + result.ReportItem.GenCoins.String(), + result.ReportItem.IssueCoins.String(), + result.ReportItem.AccBalance.String(), + result.ReportItem.RewardCoins.String(), + result.ReportItem.DelBondingTokens.String(), + result.ReportItem.DelLPTokens.String(), + result.BondingDiff.String(), + result.LPDiff.String(), + }) + if err != nil { + return fmt.Errorf("entry %d: write: %w", i+1, err) + } + } + + csvWriter.Flush() + + return nil +} + +func (results SXFIBalanceReportResults) String() string { + decimalDec := sdk.NewDecWithPrec(1, 18) + + str := strings.Builder{} + str.WriteString("Mainnet SXFI-XFI relation report:\n") + for _, result := range results { + diffBondingDec, diffLPDec := result.BondingDiff.ToDec().Mul(decimalDec), result.LPDiff.ToDec().Mul(decimalDec) + str.WriteString(fmt.Sprintf(" - %s\n", result.ReportItem.AccAddress)) + str.WriteString(fmt.Sprintf(" BondingDiff: %s (%s)\n", diffBondingDec, result.BondingDiff)) + str.WriteString(fmt.Sprintf(" LPDiff: %s (%s)\n", diffLPDec, result.LPDiff)) + str.WriteString(fmt.Sprintf(" GenBalance: %s\n", result.ReportItem.GenCoins)) + str.WriteString(fmt.Sprintf(" AccBalance: %s\n", result.ReportItem.AccBalance)) + str.WriteString(fmt.Sprintf(" Issues: %s\n", result.ReportItem.IssueCoins)) + str.WriteString(fmt.Sprintf(" Rewards: %s\n", result.ReportItem.RewardCoins)) + str.WriteString(fmt.Sprintf(" BDel: %s (%s)\n", result.ReportItem.DelBondingTokens, result.ReportItem.DelBondingShares)) + str.WriteString(fmt.Sprintf(" LPDel: %s (%s)\n", result.ReportItem.DelLPTokens, result.ReportItem.DelLPShares)) + } + + return str.String() +} + +// SXFIBalanceReport contains initial and final Testnet (v0.7) sxfi balance for accounts. +// Key - account address. +type SXFIBalanceReport map[string]*SXFIBalanceReportItem + +// AppendGenesisBalances modifies a SXFIBalanceReport with genesis account balances. +func (r SXFIBalanceReport) AppendGenesisBalances( + ctx sdk.Context, app *DnServiceApp, + issueBondingDenom, issueLPDenom, bondingDenom, lpDenom string, +) error { + + genBalances := []struct { + AccAddress string + BondingBalance string + LPBalance string + }{ + { + AccAddress: "wallet1wwmenr38hhrem2v3ue3gwdhj03ynzcvlxgc92u", + BondingBalance: "3400000000000000000000000", + LPBalance: "0", + }, + { + AccAddress: "wallet1a6sd0y8l0ma0gnytacrnwlmnupm7ftnwxngalr", + BondingBalance: "2500000000000000000000", + LPBalance: "0", + }, + { + AccAddress: "wallet1whpkntyj549f7euftgpng24k2we8legght4rzg", + BondingBalance: "2500000000000000000000", + LPBalance: "0", + }, + { + AccAddress: "wallet1zwkqfm2sdgyx0g6h2dj9em4z4kjgy5lmtnmgjd", + BondingBalance: "2500000000000000000000", + LPBalance: "0", + }, + { + AccAddress: "wallet10a24shxzjtutj637rr8shwkwaxx8paplu4vc6f", + BondingBalance: "2500000000000000000000", + LPBalance: "0", + }, + { + AccAddress: "wallet19xshddf5ww7fhd53fumly2r7lqsszz63fxca9x", + BondingBalance: "2500000000000000000000", + LPBalance: "0", + }, + { + AccAddress: "wallet1l9mukqvh0etam66dvgw99w9awv3jjv6tyh2hpc", + BondingBalance: "50000000000000000000000", + LPBalance: "0", + }, + } + + for i, genBalance := range genBalances { + accAddress, err := sdk.AccAddressFromBech32(genBalance.AccAddress) + if err != nil { + return fmt.Errorf("genBalance (%d): AccAddress (%s): invalid: %w", i, genBalance.AccAddress, err) + } + bondingAmt, ok := sdk.NewIntFromString(genBalance.BondingBalance) + if !ok { + return fmt.Errorf("genBalance (%d): BondingBalance (%s): invalid sdk.Int", i, genBalance.BondingBalance) + } + lpAmt, ok := sdk.NewIntFromString(genBalance.LPBalance) + if !ok { + return fmt.Errorf("genBalance (%d): LPBalance (%s): invalid sdk.Int", i, genBalance.LPBalance) + } + acc := app.accountKeeper.GetAccount(ctx, accAddress) + if acc == nil { + return fmt.Errorf("genBalance (%d): account (%s): not found", i, accAddress) + } + + reportItem := NewSXFIBalanceReportItem(accAddress, acc.GetCoins(), issueBondingDenom, issueLPDenom, bondingDenom, lpDenom) + reportItem.GenCoins = sdk.NewCoins( + sdk.NewCoin(bondingDenom, bondingAmt), + sdk.NewCoin(lpDenom, lpAmt), + ) + r[accAddress.String()] = reportItem + } + + return nil +} + +// AppendStakerCSVReport modifies a SXFIBalanceReport with staker CSV report data. +func (r SXFIBalanceReport) AppendStakerCSVReport(filePath string) error { + const ( + csvEntryColumns = 5 + ) + + f, err := os.Open(filePath) + if err != nil { + return fmt.Errorf("CSV staker report open: %w", err) + } + defer f.Close() + + csvReader := csv.NewReader(f) + entryIdx := 0 + for { + entryIdx++ + csvEntry, err := csvReader.Read() + if err != nil { + if err == io.EOF { + break + } + return fmt.Errorf("entry (%d): read failed: %w", entryIdx, err) + } + if entryIdx == 1 { + // skip the header + continue + } + + // parse + if len(csvEntry) != csvEntryColumns { + return fmt.Errorf("entry (%d): invalid number of columns: %d / %d", entryIdx, len(csvEntry), csvEntryColumns) + } + stakerTxHash := csvEntry[0] + if stakerTxHash == "" { + return fmt.Errorf("entry (%d): TxHash: emtpy", entryIdx) + } + stakerBondingAmt := sdk.ZeroInt() + if amtRaw := csvEntry[1]; amtRaw != "" { + amt, ok := sdk.NewIntFromString(amtRaw) + if !ok { + return fmt.Errorf("entry (%d): BondingAmount (%s): invalid sdk.Int", entryIdx, amtRaw) + } + stakerBondingAmt = amt + } + stakerAccAddress, err := sdk.AccAddressFromBech32(csvEntry[2]) + if err != nil { + return fmt.Errorf("entry (%d): AccAddress (%s): invalid sdk.AccAddress: %w", entryIdx, csvEntry[2], err) + } + stakerEthAddress := csvEntry[3] + if !helpers.IsEthereumAddress(stakerEthAddress) { + return fmt.Errorf("entry (%d): EthAddress (%s): invalid", entryIdx, stakerEthAddress) + } + stakerLPAmt := sdk.ZeroInt() + if amtRaw := csvEntry[4]; amtRaw != "" { + amt, ok := sdk.NewIntFromString(amtRaw) + if !ok { + return fmt.Errorf("entry (%d): LPAmount (%s): invalid sdk.Int", entryIdx, amtRaw) + } + stakerLPAmt = amt + } + + stakerReport := &SXFIStakerReportItem{ + TxHash: stakerTxHash, + AccAddress: stakerAccAddress, + EthAddress: stakerEthAddress, + BondingAmount: stakerBondingAmt, + LPAmount: stakerLPAmt, + } + reportItem, found := r[stakerReport.AccAddress.String()] + if !found { + return fmt.Errorf("entry (%d): reportEntry for AccAddress %s: not found", entryIdx, stakerReport.AccAddress) + } + if reportItem.StakerReport != nil { + return fmt.Errorf("entry (%d): reportEntry for AccAddress %s: StakerReport already exists", entryIdx, stakerReport.AccAddress) + } + + reportItem.StakerReport = stakerReport + } + + return nil +} + +// Verify compares issues data with Staker report data. +func (r SXFIBalanceReport) Verify() error { + for accAddr, reportItem := range r { + if reportItem.StakerReport == nil { + continue + } + + issuedBondingAmt := reportItem.IssueCoins.AmountOf(reportItem.IssueBondingDenom) + stakerBondingAmt := reportItem.StakerReport.BondingAmount + if !issuedBondingAmt.Equal(stakerBondingAmt) { + return fmt.Errorf("account %s: issued / staker Bonding amount mismatch: %s / %s", accAddr, issuedBondingAmt, stakerBondingAmt) + } + } + + return nil +} + +func (r SXFIBalanceReport) GetResults() SXFIBalanceReportResults { + results := make(SXFIBalanceReportResults, 0, len(r)) + for _, reportItem := range r { + diffBonding := reportItem.GetCurrentBondingBalance().Sub(reportItem.GetInitialBondingBalance()) + diffLP := reportItem.GetCurrentLPBalance().Sub(reportItem.GetInitialLPBalance()) + + results = append(results, SXFIBalanceReportResult{ + ReportItem: *reportItem, + BondingDiff: diffBonding, + LPDiff: diffLP, + }) + } + + sort.Slice(results, func(i, j int) bool { + return results[i].BondingDiff.LT(results[j].BondingDiff) + }) + + return results +} + +// getMainnetSXFIBalanceReport returns a SXFIBalanceReport report. +func (app *DnServiceApp) getMainnetSXFIBalanceReport(ctx sdk.Context, + issueBondingDenom, issueLPDenom, bondingDenom, lpDenom string, + stakerCSVReportPath string, +) (SXFIBalanceReport, error) { + + cacheCtx, _ := ctx.CacheContext() + + // initialize report with genesis data + report := make(SXFIBalanceReport) + if err := report.AppendGenesisBalances(ctx, app, issueBondingDenom, issueLPDenom, bondingDenom, lpDenom); err != nil { + return nil, fmt.Errorf("append genesis balances: %w", err) + } + + // iterate all issues and combine duplicate payees + for _, issue := range app.ccKeeper.GetGenesisIssues(cacheCtx) { + accAddr := issue.Payee + + reportItem, found := report[accAddr.String()] + if !found { + acc := app.accountKeeper.GetAccount(cacheCtx, accAddr) + if acc == nil { + return nil, fmt.Errorf("issue %s: getAccount for %s: not found", issue.ID, accAddr) + } + + reportItem = NewSXFIBalanceReportItem(accAddr, acc.GetCoins(), issueBondingDenom, issueLPDenom, bondingDenom, lpDenom) + } + + reportItem.IssueCoins = reportItem.IssueCoins.Add(issue.Coin) + report[accAddr.String()] = reportItem + } + + // withdraw all rewards + // as all rewards were transferred to rewards bank before, we only query the bank coins for each validator + for _, reportItem := range report { + accAddr := reportItem.AccAddress + app.distrKeeper.IterateDelegatorRewardsBankCoins(ctx, accAddr, func(_ sdk.ValAddress, coins sdk.Coins) (stop bool) { + reportItem.RewardCoins = reportItem.RewardCoins.Add(coins...) + return false + }) + } + + // unbond all delegations + // no actual undelegation is done, we just calculate delegator tokens based on shares and validator tokens + { + for _, reportItem := range report { + accAddr := reportItem.AccAddress + var iterationErr error + app.stakingKeeper.IterateDelegations( + cacheCtx, accAddr, + func(_ int64, del exported.DelegationI) (stop bool) { + val, found := app.stakingKeeper.GetValidator(cacheCtx, del.GetValidatorAddr()) + if !found { + iterationErr = fmt.Errorf("account %s: get delegation validator %s: not found", accAddr, del.GetValidatorAddr()) + return true + } + + reportItem.DelBondingShares = reportItem.DelBondingShares.Add(del.GetBondingShares()) + if !del.GetBondingShares().IsZero() { + reportItem.DelBondingTokens = reportItem.DelBondingTokens.Add(val.BondingTokensFromSharesTruncated(del.GetBondingShares())) + } + reportItem.DelLPShares = reportItem.DelLPShares.Add(del.GetLPShares()) + if !del.GetLPShares().IsZero() { + reportItem.DelLPTokens = reportItem.DelLPTokens.Add(val.LPTokensFromSharesTruncated(del.GetLPShares())) + } + + return false + }, + ) + if iterationErr != nil { + return nil, iterationErr + } + } + } + + // update report with Staker CSV-report + if stakerCSVReportPath != "" { + if err := report.AppendStakerCSVReport(stakerCSVReportPath); err != nil { + return nil, fmt.Errorf("append append StakerCSVReport: %w", err) + } + } + + return report, nil +} + +type SXFIBalanceReportStats struct { + TotalNegativeBondingDiffs sdk.Dec + TotalPositiveBondingDiffs sdk.Dec + AccMints map[string]sdk.DecCoin +} + +// processMainnetSXFIBalance builds getMainnetSXFIBalanceReport and mints and transfers negative diffs. +func (app *DnServiceApp) processMainnetSXFIBalance(ctx sdk.Context) error { + const ( + issueDenom = "sxfi" + bondingDenom = "xfi" + lpDenom = "lpt" + ) + decimalDec := sdk.NewDecWithPrec(1, 18) + + stakerReportPath := os.Getenv("DN_ZHP_STAKERREPORT_PATH") + reportOutputPrefix := os.Getenv("DN_ZHP_REPORTOUTPUT_PREFIX") + if stakerReportPath == "" { + return fmt.Errorf("envVar %q: not set", "DN_ZHP_STAKERREPORT_PATH") + } + if reportOutputPrefix == "" { + return fmt.Errorf("envVar %q: not set", "DN_ZHP_REPORTOUTPUT_PREFIX") + } + + // build report + report, err := app.getMainnetSXFIBalanceReport( + ctx, + issueDenom, lpDenom, bondingDenom, lpDenom, + stakerReportPath, + ) + if err != nil { + return fmt.Errorf("getMainnetSXFIBalanceReport: %w", err) + } + if err := report.Verify(); err != nil { + return fmt.Errorf("report verification: %w", err) + } + + // save results + results := report.GetResults() + if err := results.SaveToCSV(reportOutputPrefix + "data.csv"); err != nil { + return fmt.Errorf("saving report results to CSV: %w", err) + } + + // calculate the mint amount + positiveDiffs, negativeDiffs := sdk.ZeroInt(), sdk.ZeroInt() + stats := SXFIBalanceReportStats{ + TotalNegativeBondingDiffs: sdk.ZeroDec(), + TotalPositiveBondingDiffs: sdk.ZeroDec(), + AccMints: make(map[string]sdk.DecCoin, len(report)), + } + for _, result := range results { + if !result.BondingDiff.IsNegative() { + positiveDiffs = positiveDiffs.Add(result.BondingDiff) + continue + } + negativeDiffs = negativeDiffs.Add(result.BondingDiff) + } + negativeDiffs = negativeDiffs.MulRaw(-1) + bondingMintCoin := sdk.NewCoin(bondingDenom, negativeDiffs) + // + stats.TotalPositiveBondingDiffs = positiveDiffs.ToDec().Mul(decimalDec) + stats.TotalNegativeBondingDiffs = negativeDiffs.ToDec().Mul(decimalDec) + + // mint + if err := app.mintKeeper.MintCoins(ctx, sdk.NewCoins(bondingMintCoin)); err != nil { + return fmt.Errorf("minting bonding coins: %w", err) + } + if err := app.ccsKeeper.IncreaseCurrencySupply(ctx, bondingMintCoin); err != nil { + return fmt.Errorf("increasing ccStorage supply: %w", err) + } + + // distribute minted coins + for _, result := range results { + diff := result.BondingDiff + if !diff.IsNegative() { + continue + } + + coin := sdk.NewCoin(bondingDenom, diff.MulRaw(-1)) + if err := app.supplyKeeper.SendCoinsFromModuleToAccount(ctx, mint.ModuleName, result.ReportItem.AccAddress, sdk.NewCoins(coin)); err != nil { + return fmt.Errorf("sending minted coins to %s: %w", result.ReportItem.AccAddress, err) + } + // + stats.AccMints[result.ReportItem.AccAddress.String()] = sdk.NewDecCoinFromDec( + coin.Denom, + coin.Amount.ToDec().Mul(decimalDec), + ) + } + + // save stats + statsBz, err := json.Marshal(stats) + if err != nil { + return fmt.Errorf("stats: JSON marshal: %w", err) + } + f, err := os.Create(reportOutputPrefix + "stats.json") + if err != nil { + return fmt.Errorf("stats: creating file: %w", err) + } + defer f.Close() + if _, err := f.Write(statsBz); err != nil { + return fmt.Errorf("stats: write to file: %w", err) + } + + // check the invariants + if err := app.checkInvariants(ctx); err != nil { + return fmt.Errorf("post invariants check: %w", err) + } + + return nil +} diff --git a/app/integ_test.go b/app/integ_test.go index 179e4a5a..559ad468 100644 --- a/app/integ_test.go +++ b/app/integ_test.go @@ -560,7 +560,7 @@ func TestIntegVM_DeployModuleAndScriptViaCLI(t *testing.T) { // Test dnode <-> dvm request-retry mechanism. func TestIntegVM_RequestRetry(t *testing.T) { // TODO: Test should be rewritten as its success / failure is Moon phase dependant (not repeatable) - t.Skip() + t.Skip("skipped as the current implementation is not stable") const ( dsSocket = "ds.sock" @@ -641,7 +641,7 @@ func TestIntegVM_RequestRetry(t *testing.T) { // Test is skipped: should be used for dnode <-> dvm (uni-binary) communication over UDS debug locally (with DVM binaries). func TestIntegVM_CommunicationUDS(t *testing.T) { - t.Skip() + t.Skip("skipped as it is for local debug only") const ( dsSocket = "ds.sock" diff --git a/app/rest_test.go b/app/rest_test.go index c850618d..bc3423f0 100644 --- a/app/rest_test.go +++ b/app/rest_test.go @@ -31,6 +31,7 @@ import ( // TestSXFIBankTransaction_REST transfers for sxfi token must be disallowed func TestSXFIBankTransaction_REST(t *testing.T) { + t.Skip("skipped as dist limitations are disabled for the Mainnet") t.Parallel() ct := cliTester.New(t, false) @@ -50,6 +51,7 @@ func TestSXFIBankTransaction_REST(t *testing.T) { // TestSXFIGovDeposit_REST gov deposit allowed just for sxfi token func TestSXFIGovDeposit_REST(t *testing.T) { + t.Skip("skipped as dist limitations are disabled for the Mainnet") t.Parallel() ct := cliTester.New(t, false) diff --git a/app/unit_distribution_test.go b/app/unit_distribution_test.go index 2f0b1c95..f2715a27 100644 --- a/app/unit_distribution_test.go +++ b/app/unit_distribution_test.go @@ -15,6 +15,7 @@ import ( // Check disabled distribution transactions. func TestDistribution_MessagesNotWorking(t *testing.T) { + t.Skip("skipped as dist limitations are disabled for the Mainnet") t.Parallel() app, appStop := NewTestDnAppMockVM() diff --git a/cmd/config/genesis/defaults/common_defaults.go b/cmd/config/genesis/defaults/common_defaults.go index 5c29507a..4d363c0e 100644 --- a/cmd/config/genesis/defaults/common_defaults.go +++ b/cmd/config/genesis/defaults/common_defaults.go @@ -8,7 +8,7 @@ import ( const ( MainDenom = "xfi" - StakingDenom = "sxfi" + StakingDenom = "xfi" LiquidityProviderDenom = "lpt" // Min TX fee @@ -17,6 +17,8 @@ const ( GovMinDepositAmount = "1000000000000000000000" // 1000.0 // Staking: min self-delegation amount MinSelfDelegationAmount = "2500000000000000000000" // 2500.0 + // Staking: max self-delegation amount + MaxSelfDelegationAmount = "10000000000000000000000" // 10000.0 // Crisis: invariants check TX fee InvariantCheckAmount = "1000000000000000000000" // 1000.0 // Distribution: PublicTreasuryPool capacity @@ -29,6 +31,7 @@ var ( FeeCoin sdk.Coin GovMinDepositCoin sdk.Coin MinSelfDelegationCoin sdk.Coin + MaxSelfDelegationCoin sdk.Coin InvariantCheckCoin sdk.Coin PublicTreasuryPoolCapacity sdk.Int ) @@ -52,6 +55,12 @@ func init() { MinSelfDelegationCoin = sdk.NewCoin(StakingDenom, value) } + if value, ok := sdk.NewIntFromString(MaxSelfDelegationAmount); !ok { + panic("staking defaults: MaxSelfDelegationCoin conversion failed") + } else { + MaxSelfDelegationCoin = sdk.NewCoin(StakingDenom, value) + } + if value, ok := sdk.NewIntFromString(InvariantCheckAmount); !ok { panic("crisis defaults: InvariantCheckAmount conversion failed") } else { diff --git a/cmd/config/genesis/genesis.go b/cmd/config/genesis/genesis.go index 8b254f89..312995ea 100644 --- a/cmd/config/genesis/genesis.go +++ b/cmd/config/genesis/genesis.go @@ -104,6 +104,7 @@ func OverrideGenesisStateDefaults(cdc *codec.Codec, genState map[string]json.Raw moduleState.Params.LPDistrRatio = sdk.NewDecWithPrec(2, 0) // 200% // moduleState.Params.MinSelfDelegationLvl = defaults.MinSelfDelegationCoin.Amount // 2500.0 + moduleState.Params.MaxSelfDelegationLvl = defaults.MaxSelfDelegationCoin.Amount // 10000.0 moduleState.Params.MaxDelegationsRatio = sdk.NewDecWithPrec(10, 0) // 10.0 if moduleStateBz, err := cdc.MarshalJSON(moduleState); err != nil { diff --git a/cmd/config/restrictions/restrictions.go b/cmd/config/restrictions/restrictions.go index b8678efa..cdf9a9a1 100644 --- a/cmd/config/restrictions/restrictions.go +++ b/cmd/config/restrictions/restrictions.go @@ -5,7 +5,6 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/bank" "github.com/cosmos/cosmos-sdk/x/distribution" - "github.com/cosmos/cosmos-sdk/x/gov" "github.com/cosmos/cosmos-sdk/x/mint" "github.com/cosmos/cosmos-sdk/x/params" @@ -36,17 +35,9 @@ func GetEmptyAppRestriction() AppRestrictions { //GetAppRestrictions returns predefined parameter for remove or restrict standard app parameters. func GetAppRestrictions() AppRestrictions { return AppRestrictions{ - DisabledTxCmd: []string{ - distribution.ModuleName, - }, + DisabledTxCmd: []string{}, DisabledQueryCmd: []string{}, MsgDeniedList: map[string][]string{ - distribution.ModuleName: { - distribution.MsgWithdrawDelegatorReward{}.Type(), - distribution.MsgWithdrawValidatorCommission{}.Type(), - distribution.TypeMsgFundPublicTreasuryPool, - distribution.MsgSetWithdrawAddress{}.Type(), - }, currencies.ModuleName: { currencies.MsgWithdrawCurrency{}.Type(), }, @@ -64,16 +55,10 @@ func GetAppRestrictions() AppRestrictions { switch msg := msg.(type) { case bank.MsgSend: for i := range msg.Amount { - if msg.Amount.GetDenomByIndex(i) == defaults.StakingDenom || msg.Amount.GetDenomByIndex(i) == defaults.LiquidityProviderDenom { + if msg.Amount.GetDenomByIndex(i) == defaults.LiquidityProviderDenom { return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "bank transactions are disallowed for %s token", msg.Amount.GetDenomByIndex(i)) } } - case gov.MsgDeposit: - for i := range msg.Amount { - if msg.Amount.GetDenomByIndex(i) != defaults.StakingDenom { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "gov deposit only allowed for %s token", defaults.StakingDenom) - } - } } return nil diff --git a/go.mod b/go.mod index 6cbe1ce0..9f3810f6 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module github.com/dfinance/dnode go 1.14 -replace github.com/cosmos/cosmos-sdk => github.com/dfinance/cosmos-sdk v0.39.1-0.1 +replace github.com/cosmos/cosmos-sdk => github.com/dfinance/cosmos-sdk v0.39.2-0.20201105102202-5a9fad60516a // Local development option //replace github.com/cosmos/cosmos-sdk => /Users/boris/go/src/github.com/dfinance/cosmos-sdk diff --git a/go.sum b/go.sum index e6e05e2e..ab8bf28e 100644 --- a/go.sum +++ b/go.sum @@ -145,8 +145,8 @@ github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dfinance/cosmos-sdk v0.39.1-0.1 h1:j74lAmeScm0z6Q7+oN50E86yMkFGmgt7X4x8uZC3bPI= -github.com/dfinance/cosmos-sdk v0.39.1-0.1/go.mod h1:2sfZJgnTxx4j5VycscAUaaI3P7ay5v0AfaO/UZXTFr0= +github.com/dfinance/cosmos-sdk v0.39.2-0.20201105102202-5a9fad60516a h1:/v2aW2n3kPyaJK1TMa2SZjkVT1Rjw3dt10oqYmcJsVw= +github.com/dfinance/cosmos-sdk v0.39.2-0.20201105102202-5a9fad60516a/go.mod h1:+zeUMEhc/yfg1ChQxSI7T/J+siRbfecjZhRUolRX0oM= github.com/dfinance/dvm-proto/go v0.0.0-20201007122036-27be7297df4e h1:PT57lhHduRU0zBUO1zPHlXj48rpocTRclcAx0HLwLfQ= github.com/dfinance/dvm-proto/go v0.0.0-20201007122036-27be7297df4e/go.mod h1:Vt1T0G56AYXbsduNKzSkq1RDTNa8PFraSqB9DaTCV0U= github.com/dfinance/glav v0.0.0-20200814081332-c4701f6c12a6 h1:fZIYncA5BRad0+YnP88cfBfo0ZPgxPSVeuh/jvoGrLc= @@ -203,8 +203,6 @@ github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsouza/go-dockerclient v1.6.6-0.20200910033347-214a51d9a1e5 h1:povIUEJkhqfRW9IFv1kilK2EOwhLy3Vf9iUJ2cPI508= github.com/fsouza/go-dockerclient v1.6.6-0.20200910033347-214a51d9a1e5/go.mod h1:3/oRIWoe7uT6bwtAayj/EmJmepBjeL4pYvt7ZxC7Rnk= -github.com/g3co/go-swagger-merger v0.0.0-20200916115803-70f050d0cb09 h1:hivvvYOTeYy+Dm9nLesXatmELP5Q/4v8vyPrkZfjQs8= -github.com/g3co/go-swagger-merger v0.0.0-20200916115803-70f050d0cb09/go.mod h1:jvC3b+YoOx9/SJYqqo1pN1vJ31StlOCugGCyO3EW9XA= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/getsentry/sentry-go v0.4.0/go.mod h1:xkGcb82SipKQloDNa5b7hTV4VdEyc2bhwd1/UczP52k= @@ -250,21 +248,17 @@ github.com/go-openapi/jsonreference v0.19.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3Hfo github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= github.com/go-openapi/jsonreference v0.19.3 h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+jeTWn7tUa8o= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/jsonreference v0.19.4 h1:3Vw+rh13uq2JFNxgnMTGE1rnoieU9FmyE1gvnyylsYg= -github.com/go-openapi/jsonreference v0.19.4/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= github.com/go-openapi/spec v0.19.0 h1:A4SZ6IWh3lnjH0rG0Z5lkxazMGBECtrZcbyYQi+64k4= github.com/go-openapi/spec v0.19.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= +github.com/go-openapi/spec v0.19.4 h1:ixzUSnHTd6hCemgtAJgluaTSGYpLNpJY4mA2DIkdOAo= github.com/go-openapi/spec v0.19.4/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/spec v0.19.10 h1:pcNevfYytLaOQuTju0wm6OqcqU/E/pRwuSGigrLTI28= -github.com/go-openapi/spec v0.19.10/go.mod h1:vqK/dIdLGCosfvYsQV3WfC7N3TiZSnGY2RZKoFK7X28= github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= github.com/go-openapi/swag v0.17.0 h1:iqrgMg7Q7SvtbWLlltPrkMs0UBJI6oTSs79JFRUi880= github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.10 h1:A1SWXruroGP15P1sOiegIPbaKio+G9N5TwWTFaVPmAU= -github.com/go-openapi/swag v0.19.10/go.mod h1:Uc0gKkdR+ojzsEpjh39QChyu92vPgIr72POcgHMAgSY= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -404,8 +398,6 @@ github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -463,9 +455,8 @@ github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3bUBu+FXuk2pFbkN6tcwi/pjyaDic= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= @@ -756,8 +747,6 @@ github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k= github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= -github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4= -github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= @@ -774,7 +763,6 @@ github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmv github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zondax/hid v0.9.0 h1:eiT3P6vNxAEVxXMw66eZUAAnU2zD33JBkfG/EnfAKl8= github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= @@ -819,8 +807,6 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -850,7 +836,6 @@ golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201020065357-d65d470038a5 h1:KrxvpY64uUzANd9wKWr6ZAsufiii93XnvXaeikyCJ2g= golang.org/x/net v0.0.0-20201020065357-d65d470038a5/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -863,8 +848,6 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6 h1:DvY3Zkh7KabQE/kfzMvYvKirSiguP9Q/veMtkYyf0o8= golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -899,11 +882,8 @@ golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114 h1:DnSr2mCsxyCE6ZgIkmcWUQY2R5cH/6wL7eIxEmQOMSE= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20201019175715-b894a3290fff h1:HiwHyqQ9ttqCHuTa++R4wNxOg6MY1hduSDT8j2aXoMM= -golang.org/x/tools v0.0.0-20201019175715-b894a3290fff/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= diff --git a/helpers/tests/clitester/cli_tester_configs.go b/helpers/tests/clitester/cli_tester_configs.go index 20f9f2a2..e233a820 100644 --- a/helpers/tests/clitester/cli_tester_configs.go +++ b/helpers/tests/clitester/cli_tester_configs.go @@ -117,7 +117,7 @@ type CLIAccount struct { func NewAccountMap() (accounts map[string]*CLIAccount, retErr error) { accounts = make(map[string]*CLIAccount) - smallAmount, ok := sdk.NewIntFromString("1000000000000000000000") // 1000xfi + smallAmount, ok := sdk.NewIntFromString("100000000000000000000000") // 100000xfi if !ok { retErr = fmt.Errorf("NewInt for smallAmount") return diff --git a/helpers/tests/simulator/sim_ops_rewards_delegator.go b/helpers/tests/simulator/sim_ops_rewards_delegator.go index 91df5302..03de4296 100644 --- a/helpers/tests/simulator/sim_ops_rewards_delegator.go +++ b/helpers/tests/simulator/sim_ops_rewards_delegator.go @@ -45,7 +45,7 @@ func getDelegatorRewardOpFindTarget(s *Simulator) (targets []delegatorRewardOpTa // estimate reward coins curRewardCoins := sdk.NewCoins() - for _, decCoin := range s.QueryDistDelReward(acc.Address, delegation.ValidatorAddress).Total { + for _, decCoin := range s.QueryDistDelReward(acc.Address, delegation.ValidatorAddress).Reward.Total { coin, _ := decCoin.TruncateDecimal() curRewardCoins = curRewardCoins.Add(coin) } diff --git a/x/ccstorage/alias.go b/x/ccstorage/alias.go index 38826717..521af356 100644 --- a/x/ccstorage/alias.go +++ b/x/ccstorage/alias.go @@ -15,6 +15,8 @@ type ( ResBalance = types.ResBalance Balance = types.Balance Balances = types.Balances + // + SquashOptions = keeper.SquashOptions ) const ( @@ -35,6 +37,8 @@ var ( // function aliases NewKeeper = keeper.NewKeeper DefaultGenesisState = types.DefaultGenesisState + // + NewEmptySquashOptions = keeper.NewEmptySquashOptions // perms requests RequestVMStoragePerms = types.RequestVMStoragePerms // errors diff --git a/x/ccstorage/internal/keeper/squash.go b/x/ccstorage/internal/keeper/squash.go new file mode 100644 index 00000000..ed91ec29 --- /dev/null +++ b/x/ccstorage/internal/keeper/squash.go @@ -0,0 +1,50 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type ( + // Operations order: + // 1: supplyOp + SquashOptions struct { + // Supply modification operations + supplyOps supplyOperation + } + + supplyOperation struct { + // Set supply amount to zero + SetToZero bool + } +) + +func (opts *SquashOptions) SetSupplyOperation(toZero bool) error { + op := supplyOperation{ + SetToZero: toZero, + } + opts.supplyOps = op + + return nil +} + +func NewEmptySquashOptions() SquashOptions { + return SquashOptions{ + supplyOps: supplyOperation{}, + } +} + +// PrepareForZeroHeight squashes current context state to fit zero-height (used on genesis export). +func (k Keeper) PrepareForZeroHeight(ctx sdk.Context, opts SquashOptions) error { + // supplyOps + { + if opts.supplyOps.SetToZero { + for _, cur := range k.GetCurrencies(ctx) { + cur.Supply = sdk.ZeroInt() + k.storeCurrency(ctx, cur) + k.storeResStdCurrencyInfo(ctx, cur) + } + } + } + + return nil +} diff --git a/x/currencies/internal/keeper/genesis.go b/x/currencies/internal/keeper/genesis.go index 64af3357..ce24b1b9 100644 --- a/x/currencies/internal/keeper/genesis.go +++ b/x/currencies/internal/keeper/genesis.go @@ -61,7 +61,7 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) json.RawMessage { } // issues - state.Issues = append(state.Issues, k.getGenesisIssues(ctx)...) + state.Issues = append(state.Issues, k.GetGenesisIssues(ctx)...) // withdraws state.Withdraws = append(state.Withdraws, k.getWithdraws(ctx)...) diff --git a/x/currencies/internal/keeper/genesis_test.go b/x/currencies/internal/keeper/genesis_test.go index 85edf7d7..308b4511 100644 --- a/x/currencies/internal/keeper/genesis_test.go +++ b/x/currencies/internal/keeper/genesis_test.go @@ -76,8 +76,8 @@ func TestCurrenciesKeeper_Genesis(t *testing.T) { // lastID require.Equal(t, state.LastWithdrawID.String(), keeper.getLastWithdrawID(ctx).String()) // issues - require.Len(t, keeper.getGenesisIssues(ctx), len(state.Issues)) - for i, getIssue := range keeper.getGenesisIssues(ctx) { + require.Len(t, keeper.GetGenesisIssues(ctx), len(state.Issues)) + for i, getIssue := range keeper.GetGenesisIssues(ctx) { require.EqualValues(t, state.Issues[i], getIssue) } // withdraws @@ -96,8 +96,8 @@ func TestCurrenciesKeeper_Genesis(t *testing.T) { require.NotNil(t, state.LastWithdrawID) require.Equal(t, keeper.getLastWithdrawID(ctx).String(), state.LastWithdrawID.String()) // issues - require.Len(t, keeper.getGenesisIssues(ctx), len(state.Issues)) - for i, getIssue := range keeper.getGenesisIssues(ctx) { + require.Len(t, keeper.GetGenesisIssues(ctx), len(state.Issues)) + for i, getIssue := range keeper.GetGenesisIssues(ctx) { require.EqualValues(t, getIssue, state.Issues[i]) } // withdraws diff --git a/x/currencies/internal/keeper/issue.go b/x/currencies/internal/keeper/issue.go index 4a39e3d5..19b6d8dc 100644 --- a/x/currencies/internal/keeper/issue.go +++ b/x/currencies/internal/keeper/issue.go @@ -75,19 +75,8 @@ func (k Keeper) GetIssue(ctx sdk.Context, id string) (types.Issue, error) { return k.getIssue(ctx, id), nil } -// getIssue returns issue from the storage. -func (k Keeper) getIssue(ctx sdk.Context, id string) types.Issue { - store := ctx.KVStore(k.storeKey) - bz := store.Get(types.GetIssuesKey(id)) - - issue := types.Issue{} - k.cdc.MustUnmarshalBinaryBare(bz, &issue) - - return issue -} - -// getGenesisIssues returns all registered issues with meta (GenesisIssue) from the storage. -func (k Keeper) getGenesisIssues(ctx sdk.Context) []types.GenesisIssue { +// GetGenesisIssues returns all registered issues with meta (GenesisIssue) from the storage. +func (k Keeper) GetGenesisIssues(ctx sdk.Context) []types.GenesisIssue { issues := make([]types.GenesisIssue, 0) store := ctx.KVStore(k.storeKey) @@ -108,6 +97,17 @@ func (k Keeper) getGenesisIssues(ctx sdk.Context) []types.GenesisIssue { return issues } +// getIssue returns issue from the storage. +func (k Keeper) getIssue(ctx sdk.Context, id string) types.Issue { + store := ctx.KVStore(k.storeKey) + bz := store.Get(types.GetIssuesKey(id)) + + issue := types.Issue{} + k.cdc.MustUnmarshalBinaryBare(bz, &issue) + + return issue +} + // storeIssue sets issue to the storage. func (k Keeper) storeIssue(ctx sdk.Context, id string, issue types.Issue) { store := ctx.KVStore(k.storeKey) diff --git a/x/migration/internal/migrations/v0_7/migration.go b/x/migration/internal/migrations/v0_7/migration.go deleted file mode 100644 index e893a21a..00000000 --- a/x/migration/internal/migrations/v0_7/migration.go +++ /dev/null @@ -1,38 +0,0 @@ -package v0_7 - -import ( - "github.com/cosmos/cosmos-sdk/x/genutil" -) - -// Migrate migrates exported state from v0.6.X to a v0.7.0 genesis state. -func Migrate(appState genutil.AppMap) (genutil.AppMap, error) { - //cdcOld := codec.New() - //codec.RegisterCrypto(cdcOld) - // - //cdcNew := codec.New() - //codec.RegisterCrypto(cdcNew) - // - //// migrate multisig module - //moduleName := multisig.ModuleName - //if stateOldBz := appState[moduleName]; stateOldBz != nil { - // var oldState v06multisig.GenesisState - // if err := cdcOld.UnmarshalJSON(stateOldBz, &oldState); err != nil { - // return nil, fmt.Errorf("module %q: oldState JSON unmarshal: %w", moduleName, err) - // } - // - // newState, err := v07multisig.Migrate(oldState) - // if err != nil { - // return nil, fmt.Errorf("module %q: migration: %w", moduleName, err) - // } - // - // stateNewBz, err := cdcNew.MarshalJSON(newState) - // if err != nil { - // return nil, fmt.Errorf("module %q: newState JSON marshal: %w", moduleName, err) - // } - // - // delete(appState, moduleName) - // appState[moduleName] = stateNewBz - //} - - return appState, nil -} diff --git a/x/migration/internal/migrations/v1_0/migration.go b/x/migration/internal/migrations/v1_0/migration.go new file mode 100644 index 00000000..8b07a629 --- /dev/null +++ b/x/migration/internal/migrations/v1_0/migration.go @@ -0,0 +1,71 @@ +package v1_0 + +import ( + "fmt" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/x/distribution" + v03902distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v0_39-0_2" + v03910distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v0_39-1_0" + "github.com/cosmos/cosmos-sdk/x/genutil" + "github.com/cosmos/cosmos-sdk/x/staking" + v03902staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v0_39-0_2" + v03910staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v0_39-1_0" + + "github.com/dfinance/dnode/cmd/config/genesis/defaults" +) + +// Migrate migrates exported genesis state from Dfinance v0.7 Testnet to v1.0 Mainnet. +func Migrate(appState genutil.AppMap) (genutil.AppMap, error) { + cdcOld := codec.New() + codec.RegisterCrypto(cdcOld) + + cdcNew := codec.New() + codec.RegisterCrypto(cdcNew) + + // Cosmos SDK modules + // staking + { + moduleName := staking.ModuleName + if stateOldBz := appState[moduleName]; stateOldBz != nil { + migrationOpts := v03910staking.MigrateOptions{ + ParamsMaxSelfDelegationLvl: defaults.MaxSelfDelegationCoin.Amount, + } + + var oldState v03902staking.GenesisState + if err := cdcOld.UnmarshalJSON(stateOldBz, &oldState); err != nil { + return nil, fmt.Errorf("module %q: oldState JSON unmarshal: %w", moduleName, err) + } + + newState := v03910staking.Migrate(oldState, migrationOpts) + stateNewBz, err := cdcNew.MarshalJSON(newState) + if err != nil { + return nil, fmt.Errorf("module %q: newState JSON marshal: %w", moduleName, err) + } + + delete(appState, moduleName) + appState[moduleName] = stateNewBz + } + } + // distribution + { + moduleName := distribution.ModuleName + if stateOldBz := appState[moduleName]; stateOldBz != nil { + var oldState v03902distribution.GenesisState + if err := cdcOld.UnmarshalJSON(stateOldBz, &oldState); err != nil { + return nil, fmt.Errorf("module %q: oldState JSON unmarshal: %w", moduleName, err) + } + + newState := v03910distribution.Migrate(oldState) + stateNewBz, err := cdcNew.MarshalJSON(newState) + if err != nil { + return nil, fmt.Errorf("module %q: newState JSON marshal: %w", moduleName, err) + } + + delete(appState, moduleName) + appState[moduleName] = stateNewBz + } + } + + return appState, nil +} diff --git a/x/migration/internal/types/migration.go b/x/migration/internal/types/migration.go index 26b5f59b..6cbd77df 100644 --- a/x/migration/internal/types/migration.go +++ b/x/migration/internal/types/migration.go @@ -3,7 +3,7 @@ package types import ( "github.com/cosmos/cosmos-sdk/x/genutil" - v07 "github.com/dfinance/dnode/x/migration/internal/migrations/v0_7" + "github.com/dfinance/dnode/x/migration/internal/migrations/v1_0" ) // MigrationHandler converts an appState (genesis map) from the previous version to the targeted one. @@ -14,5 +14,5 @@ type TargetMigrationMap map[string]MigrationHandler // MigrationMap is a registered migrations map. var MigrationMap = TargetMigrationMap{ - "v0.7": v07.Migrate, + "v1.0": v1_0.Migrate, } diff --git a/x/multisig/internal/keeper/squash.go b/x/multisig/internal/keeper/squash.go new file mode 100644 index 00000000..d70a6ed7 --- /dev/null +++ b/x/multisig/internal/keeper/squash.go @@ -0,0 +1,25 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// PrepareForZeroHeight squashes current context state to fit zero-height (used on genesis export). +func (k Keeper) PrepareForZeroHeight(ctx sdk.Context) error { + // reset call objects and calls queue entries + // queue modifications resets call confirmation timeout + calls := k.getCalls(ctx) + for _, call := range calls { + // add to the queue if call is not handled yet + if err := call.CanBeVoted(); err == nil { + k.RemoveCallFromQueue(ctx, call.ID, call.Height) + k.addCallToQueue(ctx, call.ID, 0) + } + + // update call + call.Height = 0 + k.StoreCall(ctx, call) + } + + return nil +} diff --git a/x/orderbook/internal/keeper/squash.go b/x/orderbook/internal/keeper/squash.go new file mode 100644 index 00000000..ccbc34ea --- /dev/null +++ b/x/orderbook/internal/keeper/squash.go @@ -0,0 +1,35 @@ +package keeper + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/dfinance/dnode/x/orderbook/internal/types" +) + +// PrepareForZeroHeight squashes current context state to fit zero-height (used on genesis export). +func (k Keeper) PrepareForZeroHeight(ctx sdk.Context) error { + store := ctx.KVStore(k.storeKey) + + historyItems, err := k.GetHistoryItemsList(ctx) + if err != nil { + return fmt.Errorf("retrieving HistoryItem list: %w", err) + } + + // remove all but the latest history item for each market + historyItemsSet := make(map[string]types.HistoryItem) + for _, curItem := range historyItems { + existingItem, found := historyItemsSet[curItem.MarketID.String()] + if !found || curItem.BlockHeight > existingItem.BlockHeight { + historyItemsSet[curItem.MarketID.String()] = curItem + } + store.Delete(types.GetHistoryItemKey(curItem.MarketID, curItem.BlockHeight)) + } + for _, item := range historyItemsSet { + item.BlockHeight = 0 + k.SetHistoryItem(ctx, item) + } + + return nil +} diff --git a/x/vm/client/cli/tx.go b/x/vm/client/cli/tx.go index 9a45c2fb..fb20dd80 100644 --- a/x/vm/client/cli/tx.go +++ b/x/vm/client/cli/tx.go @@ -208,7 +208,7 @@ func getMoveCodeFromFileArg(argValue string, oneItem bool) (items vm_client.Comp argName, argValue, helpers.ParamTypeCliArg, - fmt.Sprintf("Move file contains different code types, allowed only similar types in one file"), + "Move file contains different code types, allowed only similar types in one file", ) return } diff --git a/x/vmauth/alias.go b/x/vmauth/alias.go index 54578324..34309185 100644 --- a/x/vmauth/alias.go +++ b/x/vmauth/alias.go @@ -13,6 +13,8 @@ import ( type ( Keeper = keeper.VMAccountKeeper GenesisState = authTypes.GenesisState + // + SquashOptions = keeper.SquashOptions ) const ( @@ -32,6 +34,8 @@ var ( GetTxCmd = authClientCli.GetTxCmd GetQueryCmd = authClientCli.GetQueryCmd DefaultGenesisState = authTypes.DefaultGenesisState + // + NewEmptySquashOptions = keeper.NewEmptySquashOptions // perms requests RequestCCStoragePerms = types.RequestCCStoragePerms ) diff --git a/x/vmauth/internal/keeper/squash.go b/x/vmauth/internal/keeper/squash.go new file mode 100644 index 00000000..13b29fde --- /dev/null +++ b/x/vmauth/internal/keeper/squash.go @@ -0,0 +1,173 @@ +package keeper + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + authexported "github.com/cosmos/cosmos-sdk/x/auth/exported" +) + +type ( + // Operations order: + // 1: addAccountOps + // 2: accountBalanceOps + SquashOptions struct { + // Add account operations + addAccountOps []addAccountOperation + // Account balance modification operations + accountBalanceOps []accountBalanceOperation + } + + addAccountOperation struct { + // Account address + Address sdk.AccAddress + // Account balance + Coins sdk.Coins + } + + accountBalanceOperation struct { + // Coin denom + Denom string + // Remove coin balance + // 1st priority + Remove bool + // Rename coin / move balance (empty - no renaming) + // 2nd priority + RenameTo string + } +) + +func (opts *SquashOptions) SetAddAccountOp(addressRaw, coinsRaw string) error { + op := addAccountOperation{} + + addr, err := sdk.AccAddressFromBech32(addressRaw) + if err != nil { + return fmt.Errorf("address (%s): invalid AccAddress: %w", addressRaw, err) + } + op.Address = addr + + coins, err := sdk.ParseCoins(coinsRaw) + if err != nil { + return fmt.Errorf("coins (%s): sdk.Coins parsing failed: %w", coinsRaw, err) + } + op.Coins = coins + + opts.addAccountOps = append(opts.addAccountOps, op) + + return nil +} + +func (opts *SquashOptions) SetAccountBalanceOp(denomRaw string, remove bool, renameToRaw string) error { + op := accountBalanceOperation{} + op.Remove = remove + + if remove && renameToRaw != "" { + return fmt.Errorf("remove op can not coexist with rename op") + } + + if err := sdk.ValidateDenom(denomRaw); err != nil { + return fmt.Errorf("denom (%s): invalid: %w", denomRaw, err) + } + op.Denom = denomRaw + + if renameToRaw != "" { + if err := sdk.ValidateDenom(renameToRaw); err != nil { + return fmt.Errorf("renameTo denom (%s): invalid: %w", renameToRaw, err) + } + op.RenameTo = renameToRaw + } + + opts.accountBalanceOps = append(opts.accountBalanceOps, op) + + return nil +} + +func NewEmptySquashOptions() SquashOptions { + return SquashOptions{ + addAccountOps: nil, + accountBalanceOps: nil, + } +} + +// PrepareForZeroHeight squashes current context state to fit zero-height (used on genesis export). +func (k VMAccountKeeper) PrepareForZeroHeight(ctx sdk.Context, opts SquashOptions) error { + // addAccountOps + for i, accOpt := range opts.addAccountOps { + acc := k.NewAccountWithAddress(ctx, accOpt.Address) + if err := acc.SetCoins(accOpt.Coins); err != nil { + return fmt.Errorf("addAccountOps[%d]: SetCoins: %w", i, err) + } + k.SetAccount(ctx, acc) + } + + // accountBalanceOps + { + // remove ops + for i, op := range opts.accountBalanceOps { + if !op.Remove { + continue + } + + var opErr error + k.IterateAccounts(ctx, func(acc authexported.Account) (stop bool) { + coins := acc.GetCoins() + coinToDel := sdk.NewCoin(op.Denom, sdk.ZeroInt()) + for _, coin := range coins { + if coin.Denom != op.Denom { + continue + } + coinToDel.Amount = coin.Amount + break + } + + coins = coins.Sub(sdk.NewCoins(coinToDel)) + if err := acc.SetCoins(coins); err != nil { + opErr = fmt.Errorf("accountBalanceOps[%d] (%s) remove: SetCoins: %w", i, acc.GetAddress(), err) + return true + } + k.SetAccount(ctx, acc) + + return false + }) + if opErr != nil { + return opErr + } + } + + // rename ops + for i, op := range opts.accountBalanceOps { + if op.RenameTo == "" { + continue + } + + var opErr error + k.IterateAccounts(ctx, func(acc authexported.Account) (stop bool) { + coins := acc.GetCoins() + oldCoin := sdk.NewCoin(op.Denom, sdk.ZeroInt()) + for _, coin := range coins { + if coin.Denom != op.Denom { + continue + } + oldCoin.Amount = coin.Amount + break + } + newCoin := sdk.NewCoin(op.RenameTo, oldCoin.Amount) + + coins = coins.Sub(sdk.NewCoins(oldCoin)) + coins = coins.Add(newCoin) + if err := acc.SetCoins(coins); err != nil { + opErr = fmt.Errorf("accountBalanceOps[%d] (%s) rename: SetCoins: %w", i, acc.GetAddress(), err) + return true + } + k.SetAccount(ctx, acc) + + return false + }) + if opErr != nil { + return opErr + } + } + } + + return nil +}