0g-chain/migrate/v0_16/migrate_test.go

184 lines
8.0 KiB
Go

package v0_16
import (
"io/ioutil"
"path/filepath"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
v039auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v039"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
vestexported "github.com/cosmos/cosmos-sdk/x/auth/vesting/exported"
vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
v036supply "github.com/cosmos/cosmos-sdk/x/bank/legacy/v036"
v038bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v038"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
tmjson "github.com/tendermint/tendermint/libs/json"
tmtypes "github.com/tendermint/tendermint/types"
"github.com/kava-labs/kava/app"
"github.com/kava-labs/kava/migrate/v0_16/legacyaccounts"
)
func TestMigrateGenesisDoc(t *testing.T) {
expected := getTestDataJSON("genesis-v16.json")
genDoc, err := tmtypes.GenesisDocFromFile(filepath.Join("testdata", "genesis-v15.json"))
assert.NoError(t, err)
actualGenDoc, err := Migrate(genDoc, newClientContext())
assert.NoError(t, err)
actualJson, err := tmjson.Marshal(actualGenDoc)
assert.NoError(t, err)
assert.JSONEq(t, expected, string(actualJson))
assert.LessOrEqual(t, actualGenDoc.ConsensusParams.Evidence.MaxBytes, actualGenDoc.ConsensusParams.Block.MaxBytes)
}
func TestMigrateFull(t *testing.T) {
t.Skip() // avoid committing mainnet state - test also currently fails due to https://github.com/cosmos/cosmos-sdk/issues/10862. If you apply the patch, it will pass
genDoc, err := tmtypes.GenesisDocFromFile(filepath.Join("testdata", "kava-8-block-1627000.json"))
assert.NoError(t, err)
newGenDoc, err := Migrate(genDoc, newClientContext())
assert.NoError(t, err)
encodingConfig := app.MakeEncodingConfig()
var appMap genutiltypes.AppMap
err = tmjson.Unmarshal(newGenDoc.AppState, &appMap)
assert.NoError(t, err)
err = app.ModuleBasics.ValidateGenesis(encodingConfig.Marshaler, encodingConfig.TxConfig, appMap)
assert.NoError(t, err)
tApp := app.NewTestApp()
require.NotPanics(t, func() {
tApp.InitializeFromGenesisStatesWithTimeAndChainID(newGenDoc.GenesisTime, newGenDoc.ChainID, app.GenesisState(appMap))
})
}
func TestAccountBalances(t *testing.T) {
t.Skip() // avoid committing test data
setConfigIfUnsealed()
// load auth state from kava-8 with empty accounts removed (keeps size down)
authbz, err := ioutil.ReadFile(filepath.Join("testdata", "kava-8-test-auth-state.json"))
require.NoError(t, err)
// load bank state from kava-8, required for migration
bankbz, err := ioutil.ReadFile(filepath.Join("testdata", "kava-8-test-bank-state.json"))
require.NoError(t, err)
// load supply state from kava-8, required for migration
supplybz, err := ioutil.ReadFile(filepath.Join("testdata", "kava-8-test-supply-state.json"))
require.NoError(t, err)
// codec to read old auth data
v039Codec := codec.NewLegacyAmino()
legacyaccounts.RegisterLegacyAminoCodec(v039Codec)
// store old auth genesis state for comparison to migrated state
var prevAuthGenState legacyaccounts.GenesisState
v039Codec.MustUnmarshalJSON(authbz, &prevAuthGenState)
// migrate auth state to kava-9, with periodic vesting account changes and bank conversion
appState := genutiltypes.AppMap{
v039auth.ModuleName: authbz,
v038bank.ModuleName: bankbz,
v036supply.ModuleName: supplybz,
}
clientCtx := newClientContext()
appState = MigrateCosmosAppState(appState, clientCtx, GenesisTime)
// store new auth and bank state
var migratedAuthGenState authtypes.GenesisState
clientCtx.Codec.MustUnmarshalJSON(appState[authtypes.ModuleName], &migratedAuthGenState)
var migratedBankGenState banktypes.GenesisState
clientCtx.Codec.MustUnmarshalJSON(appState[banktypes.ModuleName], &migratedBankGenState)
// store map of accouauthexportednt coins from the bank module
migratedAccCoins := make(map[string]sdk.Coins)
for _, bal := range migratedBankGenState.Balances {
migratedAccCoins[bal.Address] = bal.Coins
}
for i, anyAcc := range migratedAuthGenState.Accounts {
var acc authtypes.AccountI
err := clientCtx.InterfaceRegistry.UnpackAny(anyAcc, &acc)
require.NoError(t, err)
oldAcc := prevAuthGenState.Accounts[i]
oldAcc.SpendableCoins(GenesisTime)
newBalance, ok := migratedAccCoins[acc.GetAddress().String()]
// all accounts have a corresponding balance
require.True(t, ok, "expected balance to exist")
// this is the same account
require.Equal(t, oldAcc.GetAddress(), acc.GetAddress(), "expected account address to match")
// the owned coins did not change
require.Equal(t, oldAcc.GetCoins(), newBalance, "expected base coins to not change")
// ensure spenable coins at genesis time is equal
require.Equal(t, oldAcc.SpendableCoins(GenesisTime), getSpendableCoinsForAccount(acc, newBalance, GenesisTime), "expected spendable coins to not change")
// check 30 days
futureDate := GenesisTime.Add(30 * 24 * time.Hour)
require.Equal(t, oldAcc.SpendableCoins(futureDate), getSpendableCoinsForAccount(acc, newBalance, futureDate), "expected spendable coins to not change")
// check 90 days
futureDate = GenesisTime.Add(90 * 24 * time.Hour)
require.Equal(t, oldAcc.SpendableCoins(futureDate), getSpendableCoinsForAccount(acc, newBalance, futureDate), "expected spendable coins to not change")
// check 180 days
futureDate = GenesisTime.Add(180 * 24 * time.Hour)
require.Equal(t, oldAcc.SpendableCoins(futureDate), getSpendableCoinsForAccount(acc, newBalance, futureDate), "expected spendable coins to not change")
// check 365 days
futureDate = GenesisTime.Add(365 * 24 * time.Hour)
require.Equal(t, oldAcc.SpendableCoins(futureDate), getSpendableCoinsForAccount(acc, newBalance, futureDate), "expected spendable coins to not change")
// check 2 years
futureDate = GenesisTime.Add(2 * 365 * 24 * time.Hour)
require.Equal(t, oldAcc.SpendableCoins(futureDate), getSpendableCoinsForAccount(acc, newBalance, futureDate), "expected spendable coins to not change")
if vacc, ok := acc.(*vestingtypes.PeriodicVestingAccount); ok {
// old account must be a periodic vesting account
oldVacc, ok := oldAcc.(*legacyaccounts.PeriodicVestingAccount)
require.True(t, ok)
// total delegated coins must match
oldTotalDelegated := oldVacc.DelegatedFree.Add(oldVacc.DelegatedVesting...)
newTotalDelegated := vacc.DelegatedFree.Add(vacc.DelegatedVesting...)
require.Equal(t, oldTotalDelegated, newTotalDelegated, "expected total amount of tracked delegations to not change")
// delegated vesting must be less or equal to original vesting
require.True(t, vacc.DelegatedVesting.IsAllLTE(vacc.OriginalVesting), "expected delegated vesting to be less or equal to original vesting")
// vested coins must be nil for the new account
require.Equal(t, sdk.Coins(nil), vacc.GetVestedCoins(GenesisTime), "expected no vested coins at genesis time")
// vesting coins must not be nil
require.NotEqual(t, sdk.Coins(nil), vacc.GetVestingCoins(GenesisTime), "expected vesting coins to be greater than 0")
// new account as less than or equal
require.LessOrEqual(t, len(vacc.VestingPeriods), len(oldVacc.VestingPeriods), "expected vesting periods of new account to be less than or equal to old")
// start time should equal genesis time
require.Equal(t, vacc.StartTime, GenesisTime.Unix(), "expected start time to be equal to genesis time")
// end time should not change
require.Equal(t, oldVacc.EndTime, vacc.EndTime, "expected end time to not change")
// end time should be after genesis time
require.Greater(t, vacc.EndTime, GenesisTime.Unix(), "expected end time to be after genesis time")
// vesting account must have one or more periods
require.GreaterOrEqual(t, len(vacc.VestingPeriods), 1, "expected one or more vesting periods")
}
}
}
func getSpendableCoinsForAccount(acc authtypes.AccountI, balance sdk.Coins, blockTime time.Time) sdk.Coins {
if vacc, ok := acc.(vestexported.VestingAccount); ok {
return balance.Sub(vacc.LockedCoins(blockTime))
}
return balance
}