mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-26 00:05:18 +00:00
Reset Periodic Vesting Accounts for Kava-8 (#987)
* add auth test data * add periodic vesting account migration * assert owned coins are equal and unchanged during migration * add script for generating test data from a genesis file * remove commented import * touch ups * don't pretty print test data for auth module; update generate script to use jq -c option * fix typo in comment, improve clarity of assertions * add context to migrate auth assertions * add 180 days check for spendable coins * asssertion context * pr feedback - add assertions, touch up assertion msgs, and fix migration test to correctly type assert pointer
This commit is contained in:
parent
58b3089ecd
commit
8b54fdafa4
75
migrate/v0_15/account.go
Normal file
75
migrate/v0_15/account.go
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
package v0_15
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
authexported "github.com/cosmos/cosmos-sdk/x/auth/exported"
|
||||||
|
vesting "github.com/cosmos/cosmos-sdk/x/auth/vesting"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MigrateAccount removes old vesting periods from periodic vesting accounts
|
||||||
|
// and converts any periodic vesting account with zero periods back to a base account
|
||||||
|
func MigrateAccount(acc authexported.GenesisAccount, genesisTime time.Time) authexported.GenesisAccount {
|
||||||
|
if vacc, ok := acc.(*vesting.PeriodicVestingAccount); ok {
|
||||||
|
ResetPeriodicVestingAccount(vacc, genesisTime)
|
||||||
|
|
||||||
|
if genesisTime.Unix() >= vacc.EndTime {
|
||||||
|
return vacc.BaseVestingAccount.BaseAccount
|
||||||
|
}
|
||||||
|
|
||||||
|
return vacc
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResetPeriodicVestingAccount resets a periodic vesting account to a new start time. The account is
|
||||||
|
// modified in place, and vesting periods before the new start time are removed from the account.
|
||||||
|
func ResetPeriodicVestingAccount(vacc *vesting.PeriodicVestingAccount, startTime time.Time) {
|
||||||
|
currentPeriod := vacc.StartTime
|
||||||
|
|
||||||
|
newOriginalVesting := sdk.Coins{}
|
||||||
|
newStartTime := startTime.Unix()
|
||||||
|
newEndTime := newStartTime
|
||||||
|
newPeriods := vesting.Periods{}
|
||||||
|
|
||||||
|
for _, period := range vacc.VestingPeriods {
|
||||||
|
currentPeriod := currentPeriod + period.Length
|
||||||
|
|
||||||
|
// Periods less than or equal to the newStartTime are still vesting,
|
||||||
|
// so adjust their length and add them to them to the newPeriods
|
||||||
|
if newStartTime <= currentPeriod {
|
||||||
|
period.Length = currentPeriod - newStartTime
|
||||||
|
|
||||||
|
newEndTime = newEndTime + period.Length
|
||||||
|
newOriginalVesting = newOriginalVesting.Add(period.Amount...)
|
||||||
|
|
||||||
|
newPeriods = append(newPeriods, period)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// In order to preserve the spendable amount of the account, we must drop
|
||||||
|
// the vesting funds if the start and end time are equal.
|
||||||
|
if newStartTime == newEndTime {
|
||||||
|
newOriginalVesting = sdk.Coins{}
|
||||||
|
newPeriods = vesting.Periods{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the new original vesting amount is less than the delegated vesting amount, set delegated vesting
|
||||||
|
// to the new original vesting amount, and add the difference to the delegated free amount
|
||||||
|
for _, delegatedVestingCoin := range vacc.DelegatedVesting {
|
||||||
|
newDelegatedVestingCoin := sdk.NewCoin(delegatedVestingCoin.Denom, sdk.MinInt(delegatedVestingCoin.Amount, newOriginalVesting.AmountOf(delegatedVestingCoin.Denom)))
|
||||||
|
delegationAdjustment := delegatedVestingCoin.Sub(newDelegatedVestingCoin)
|
||||||
|
|
||||||
|
if !delegationAdjustment.IsZero() {
|
||||||
|
vacc.DelegatedVesting = vacc.DelegatedVesting.Sub(sdk.NewCoins(delegationAdjustment))
|
||||||
|
vacc.DelegatedFree = vacc.DelegatedFree.Add(delegationAdjustment)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vacc.StartTime = newStartTime
|
||||||
|
vacc.EndTime = newEndTime
|
||||||
|
vacc.OriginalVesting = newOriginalVesting
|
||||||
|
vacc.VestingPeriods = newPeriods
|
||||||
|
}
|
291
migrate/v0_15/account_test.go
Normal file
291
migrate/v0_15/account_test.go
Normal file
@ -0,0 +1,291 @@
|
|||||||
|
package v0_15
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
auth "github.com/cosmos/cosmos-sdk/x/auth"
|
||||||
|
vesting "github.com/cosmos/cosmos-sdk/x/auth/vesting"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/tendermint/tendermint/crypto/secp256k1"
|
||||||
|
)
|
||||||
|
|
||||||
|
func createVestingAccount(balance sdk.Coins, vestingStart time.Time, vestingPeriods vesting.Periods) *vesting.PeriodicVestingAccount {
|
||||||
|
key := secp256k1.GenPrivKey()
|
||||||
|
pub := key.PubKey()
|
||||||
|
addr := sdk.AccAddress(pub.Address())
|
||||||
|
acc := auth.NewBaseAccount(addr, balance, pub, 1, 1)
|
||||||
|
|
||||||
|
return vesting.NewPeriodicVestingAccount(acc, vestingStart.Unix(), vestingPeriods)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMigrateAccount_BaseAccount(t *testing.T) {
|
||||||
|
balance := sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1e6)))
|
||||||
|
|
||||||
|
key := secp256k1.GenPrivKey()
|
||||||
|
pub := key.PubKey()
|
||||||
|
addr := sdk.AccAddress(pub.Address())
|
||||||
|
acc := auth.NewBaseAccount(addr, balance, pub, 1, 1)
|
||||||
|
|
||||||
|
accCopy := *acc
|
||||||
|
migratedAcc := MigrateAccount(&accCopy, time.Now())
|
||||||
|
|
||||||
|
assert.Equal(t, acc, migratedAcc, "expected account to be unmodified")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMigrateAccount_PeriodicVestingAccount_NoPeriods(t *testing.T) {
|
||||||
|
balance := sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1e6)))
|
||||||
|
|
||||||
|
key := secp256k1.GenPrivKey()
|
||||||
|
pub := key.PubKey()
|
||||||
|
addr := sdk.AccAddress(pub.Address())
|
||||||
|
acc := auth.NewBaseAccount(addr, balance, pub, 1, 1)
|
||||||
|
|
||||||
|
vacc := vesting.NewPeriodicVestingAccount(acc, time.Now().Unix(), vesting.Periods{})
|
||||||
|
migratedAcc := MigrateAccount(vacc, time.Now())
|
||||||
|
|
||||||
|
assert.Equal(t, acc, migratedAcc, "expected base account to be returned")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMigrateAccount_PeriodicVestingAccount_Vesting(t *testing.T) {
|
||||||
|
balance := sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(3e6)))
|
||||||
|
vestingStartTime := time.Now().Add(-30 * 24 * time.Hour) // 30 days in past
|
||||||
|
|
||||||
|
periods := vesting.Periods{
|
||||||
|
vesting.Period{
|
||||||
|
Length: 15 * 24 * 60 * 60, // -15 days - vested
|
||||||
|
Amount: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1e6))),
|
||||||
|
},
|
||||||
|
vesting.Period{
|
||||||
|
Length: 45 * 24 * 60 * 60, // +15 days - vesting
|
||||||
|
Amount: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(2e6))),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
vacc := createVestingAccount(balance, vestingStartTime, periods)
|
||||||
|
genesisTime := vestingStartTime.Add(30 * 24 * time.Hour)
|
||||||
|
|
||||||
|
MigrateAccount(vacc, genesisTime)
|
||||||
|
|
||||||
|
expectedVestingPeriods := vesting.Periods{
|
||||||
|
vesting.Period{
|
||||||
|
Length: 15 * 24 * 60 * 60,
|
||||||
|
Amount: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(2e6))),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, genesisTime.Unix(), vacc.StartTime, "expected vesting start time to equal genesis time")
|
||||||
|
assert.Equal(t, expectedVestingPeriods, vacc.VestingPeriods, "expected only one vesting period left")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResetPeriodVestingAccount_NoVestingPeriods(t *testing.T) {
|
||||||
|
vestingStartTime := time.Now().Add(-1 * time.Hour)
|
||||||
|
vacc := createVestingAccount(sdk.Coins{}, vestingStartTime, vesting.Periods{})
|
||||||
|
|
||||||
|
newVestingStartTime := vestingStartTime.Add(time.Hour)
|
||||||
|
spendableBefore := vacc.SpendableCoins(newVestingStartTime)
|
||||||
|
|
||||||
|
ResetPeriodicVestingAccount(vacc, newVestingStartTime)
|
||||||
|
|
||||||
|
assert.Equal(t, sdk.Coins{}, vacc.OriginalVesting, "expected original vesting to be zero")
|
||||||
|
assert.Equal(t, newVestingStartTime.Unix(), vacc.StartTime, "expected vesting start time to be updated")
|
||||||
|
assert.Equal(t, newVestingStartTime.Unix(), vacc.EndTime, "expected vesting end time to be updated")
|
||||||
|
assert.Equal(t, vesting.Periods{}, vacc.VestingPeriods, "expected vesting periods to be empty")
|
||||||
|
assert.Equal(t, spendableBefore, vacc.SpendableCoins(newVestingStartTime), "expected spendable coins to be unchanged")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResetPeriodVestingAccount_SingleVestingPeriod_Vested(t *testing.T) {
|
||||||
|
balance := sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1e6)))
|
||||||
|
vestingStartTime := time.Now().Add(-30 * 24 * time.Hour) // 30 days in past
|
||||||
|
|
||||||
|
periods := vesting.Periods{
|
||||||
|
vesting.Period{
|
||||||
|
Length: 15 * 24 * 60 * 60, // 15 days (-15 days in past)
|
||||||
|
Amount: balance,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
vacc := createVestingAccount(balance, vestingStartTime, periods)
|
||||||
|
|
||||||
|
newVestingStartTime := vestingStartTime.Add(30 * 24 * time.Hour)
|
||||||
|
spendableBefore := vacc.SpendableCoins(newVestingStartTime)
|
||||||
|
|
||||||
|
ResetPeriodicVestingAccount(vacc, newVestingStartTime)
|
||||||
|
|
||||||
|
assert.Equal(t, sdk.Coins{}, vacc.OriginalVesting, "expected original vesting to be zero")
|
||||||
|
assert.Equal(t, newVestingStartTime.Unix(), vacc.StartTime, "expected vesting start time to be updated")
|
||||||
|
assert.Equal(t, newVestingStartTime.Unix(), vacc.EndTime, "expected vesting end time to be updated")
|
||||||
|
assert.Equal(t, vesting.Periods{}, vacc.VestingPeriods, "expected vesting periods to be empty")
|
||||||
|
assert.Equal(t, spendableBefore, vacc.SpendableCoins(newVestingStartTime), "expected spendable coins to be unchanged")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResetPeriodVestingAccount_SingleVestingPeriod_Vesting(t *testing.T) {
|
||||||
|
balance := sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1e6)))
|
||||||
|
vestingStartTime := time.Now().Add(-30 * 24 * time.Hour) // 30 days in past
|
||||||
|
|
||||||
|
periods := vesting.Periods{
|
||||||
|
vesting.Period{
|
||||||
|
Length: 45 * 24 * 60 * 60, // 45 days
|
||||||
|
Amount: balance,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
vacc := createVestingAccount(balance, vestingStartTime, periods)
|
||||||
|
|
||||||
|
newVestingStartTime := vestingStartTime.Add(30 * 24 * time.Hour)
|
||||||
|
spendableBefore := vacc.SpendableCoins(newVestingStartTime)
|
||||||
|
|
||||||
|
ResetPeriodicVestingAccount(vacc, newVestingStartTime)
|
||||||
|
|
||||||
|
// new period length 15 days
|
||||||
|
expectedEndtime := newVestingStartTime.Add(15 * 24 * time.Hour).Unix()
|
||||||
|
// new period length changed, amount unchanged
|
||||||
|
expectedPeriods := vesting.Periods{
|
||||||
|
vesting.Period{
|
||||||
|
Length: 15 * 24 * 60 * 60, // 15 days
|
||||||
|
Amount: balance,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, balance, vacc.OriginalVesting, "expected original vesting to be unchanged")
|
||||||
|
assert.Equal(t, newVestingStartTime.Unix(), vacc.StartTime, "expected vesting start time to be updated")
|
||||||
|
assert.Equal(t, expectedEndtime, vacc.EndTime, "expected vesting end time end at last period")
|
||||||
|
assert.Equal(t, expectedPeriods, vacc.VestingPeriods, "expected vesting periods to be updated")
|
||||||
|
assert.Equal(t, spendableBefore, vacc.SpendableCoins(newVestingStartTime), "expected spendable coins to be unchanged")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResetPeriodVestingAccount_SingleVestingPeriod_ExactStartTime(t *testing.T) {
|
||||||
|
balance := sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1e6)))
|
||||||
|
vestingStartTime := time.Now().Add(-30 * 24 * time.Hour) // 30 days in past
|
||||||
|
|
||||||
|
periods := vesting.Periods{
|
||||||
|
vesting.Period{
|
||||||
|
Length: 30 * 24 * 60 * 60, // 30 days - exact on the start time
|
||||||
|
Amount: balance,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
vacc := createVestingAccount(balance, vestingStartTime, periods)
|
||||||
|
|
||||||
|
newVestingStartTime := vestingStartTime.Add(30 * 24 * time.Hour)
|
||||||
|
spendableBefore := vacc.SpendableCoins(newVestingStartTime)
|
||||||
|
|
||||||
|
ResetPeriodicVestingAccount(vacc, newVestingStartTime)
|
||||||
|
|
||||||
|
// new period length is 0
|
||||||
|
expectedEndtime := newVestingStartTime.Unix()
|
||||||
|
// new period length changed, amount unchanged
|
||||||
|
expectedPeriods := vesting.Periods{}
|
||||||
|
|
||||||
|
assert.Equal(t, sdk.Coins{}, vacc.OriginalVesting, "expected original vesting to be unchanged")
|
||||||
|
assert.Equal(t, newVestingStartTime.Unix(), vacc.StartTime, "expected vesting start time to be updated")
|
||||||
|
assert.Equal(t, expectedEndtime, vacc.EndTime, "expected vesting end time end at last period")
|
||||||
|
assert.Equal(t, expectedPeriods, vacc.VestingPeriods, "expected vesting periods to be updated")
|
||||||
|
assert.Equal(t, spendableBefore, vacc.SpendableCoins(newVestingStartTime), "expected spendable coins to be unchanged")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResetPeriodVestingAccount_MultiplePeriods(t *testing.T) {
|
||||||
|
balance := sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(3e6)))
|
||||||
|
vestingStartTime := time.Now().Add(-30 * 24 * time.Hour) // 30 days in past
|
||||||
|
|
||||||
|
periods := vesting.Periods{
|
||||||
|
vesting.Period{
|
||||||
|
Length: 15 * 24 * 60 * 60, // -15 days - vested
|
||||||
|
Amount: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1e6))),
|
||||||
|
},
|
||||||
|
vesting.Period{
|
||||||
|
Length: 30 * 24 * 60 * 60, // 0 days - exact on the start time
|
||||||
|
Amount: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1e6))),
|
||||||
|
},
|
||||||
|
vesting.Period{
|
||||||
|
Length: 45 * 24 * 60 * 60, // +15 days - vesting
|
||||||
|
Amount: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1e6))),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
vacc := createVestingAccount(balance, vestingStartTime, periods)
|
||||||
|
|
||||||
|
newVestingStartTime := vestingStartTime.Add(30 * 24 * time.Hour)
|
||||||
|
spendableBefore := vacc.SpendableCoins(newVestingStartTime)
|
||||||
|
|
||||||
|
ResetPeriodicVestingAccount(vacc, newVestingStartTime)
|
||||||
|
|
||||||
|
// new period length 15 days
|
||||||
|
expectedEndtime := newVestingStartTime.Add(15 * 24 * time.Hour).Unix()
|
||||||
|
// new period length changed, amount unchanged
|
||||||
|
expectedPeriods := vesting.Periods{
|
||||||
|
vesting.Period{
|
||||||
|
Length: 0, // 0 days
|
||||||
|
Amount: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1e6))),
|
||||||
|
},
|
||||||
|
vesting.Period{
|
||||||
|
Length: 15 * 24 * 60 * 60, // 15 days
|
||||||
|
Amount: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1e6))),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(2e6))), vacc.OriginalVesting, "expected original vesting to be updated")
|
||||||
|
assert.Equal(t, newVestingStartTime.Unix(), vacc.StartTime, "expected vesting start time to be updated")
|
||||||
|
assert.Equal(t, expectedEndtime, vacc.EndTime, "expected vesting end time end at last period")
|
||||||
|
assert.Equal(t, expectedPeriods, vacc.VestingPeriods, "expected vesting periods to be updated")
|
||||||
|
assert.Equal(t, spendableBefore, vacc.SpendableCoins(newVestingStartTime), "expected spendable coins to be unchanged")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResetPeriodVestingAccount_DelegatedVesting_GreaterThanVesting(t *testing.T) {
|
||||||
|
balance := sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(3e6)))
|
||||||
|
vestingStartTime := time.Now().Add(-30 * 24 * time.Hour) // 30 days in past
|
||||||
|
|
||||||
|
periods := vesting.Periods{
|
||||||
|
vesting.Period{
|
||||||
|
Length: 15 * 24 * 60 * 60, // -15 days - vested
|
||||||
|
Amount: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1e6))),
|
||||||
|
},
|
||||||
|
vesting.Period{
|
||||||
|
Length: 30 * 24 * 60 * 60, // 0 days - exact on the start time
|
||||||
|
Amount: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1e6))),
|
||||||
|
},
|
||||||
|
vesting.Period{
|
||||||
|
Length: 45 * 24 * 60 * 60, // +15 days - vesting
|
||||||
|
Amount: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1e6))),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
vacc := createVestingAccount(balance, vestingStartTime, periods)
|
||||||
|
vacc.TrackDelegation(vestingStartTime, balance)
|
||||||
|
|
||||||
|
newVestingStartTime := vestingStartTime.Add(30 * 24 * time.Hour)
|
||||||
|
ResetPeriodicVestingAccount(vacc, newVestingStartTime)
|
||||||
|
|
||||||
|
assert.Equal(t, sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1e6))), vacc.DelegatedFree, "expected delegated free to be updated")
|
||||||
|
assert.Equal(t, sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(2e6))), vacc.DelegatedVesting, "expected delegated vesting to be updated")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResetPeriodVestingAccount_DelegatedVesting_LessThanVested(t *testing.T) {
|
||||||
|
balance := sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(3e6)))
|
||||||
|
vestingStartTime := time.Now().Add(-30 * 24 * time.Hour) // 30 days in past
|
||||||
|
|
||||||
|
periods := vesting.Periods{
|
||||||
|
vesting.Period{
|
||||||
|
Length: 15 * 24 * 60 * 60, // -15 days - vested
|
||||||
|
Amount: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1e6))),
|
||||||
|
},
|
||||||
|
vesting.Period{
|
||||||
|
Length: 30 * 24 * 60 * 60, // 0 days - exact on the start time
|
||||||
|
Amount: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1e6))),
|
||||||
|
},
|
||||||
|
vesting.Period{
|
||||||
|
Length: 45 * 24 * 60 * 60, // +15 days - vesting
|
||||||
|
Amount: sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1e6))),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
vacc := createVestingAccount(balance, vestingStartTime, periods)
|
||||||
|
vacc.TrackDelegation(vestingStartTime, sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1e6))))
|
||||||
|
|
||||||
|
newVestingStartTime := vestingStartTime.Add(30 * 24 * time.Hour)
|
||||||
|
ResetPeriodicVestingAccount(vacc, newVestingStartTime)
|
||||||
|
|
||||||
|
assert.Equal(t, sdk.Coins(nil), vacc.DelegatedFree, "expected delegrated free to be unmodified")
|
||||||
|
assert.Equal(t, sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1e6))), vacc.DelegatedVesting, "expected delegated vesting to be unmodified")
|
||||||
|
}
|
9
migrate/v0_15/generate-test-auth-data.sh
Executable file
9
migrate/v0_15/generate-test-auth-data.sh
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
if [ -z "$1" ]
|
||||||
|
then
|
||||||
|
echo "Usage: ./generate-test-auth-data.sh genesis.json"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
jq < "$1" -c '.app_state.auth | { params: .params, accounts: [.accounts[] | select((.value.coins | length) > 0)] }' > testdata/kava-7-test-auth-state.json
|
@ -5,7 +5,11 @@ import (
|
|||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||||
|
authexported "github.com/cosmos/cosmos-sdk/x/auth/exported"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth/vesting"
|
||||||
"github.com/cosmos/cosmos-sdk/x/genutil"
|
"github.com/cosmos/cosmos-sdk/x/genutil"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/supply"
|
||||||
cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino"
|
cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino"
|
||||||
tmtypes "github.com/tendermint/tendermint/types"
|
tmtypes "github.com/tendermint/tendermint/types"
|
||||||
|
|
||||||
@ -15,11 +19,12 @@ import (
|
|||||||
v0_14incentive "github.com/kava-labs/kava/x/incentive/legacy/v0_14"
|
v0_14incentive "github.com/kava-labs/kava/x/incentive/legacy/v0_14"
|
||||||
v0_15incentive "github.com/kava-labs/kava/x/incentive/types"
|
v0_15incentive "github.com/kava-labs/kava/x/incentive/types"
|
||||||
v0_15swap "github.com/kava-labs/kava/x/swap/types"
|
v0_15swap "github.com/kava-labs/kava/x/swap/types"
|
||||||
|
v0_14validator_vesting "github.com/kava-labs/kava/x/validator-vesting"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// TODO: update GenesisTime and chain-id for kava-8 launch
|
// TODO: update GenesisTime and chain-id for kava-8 launch
|
||||||
GenesisTime = time.Date(2021, 4, 8, 15, 0, 0, 0, time.UTC)
|
GenesisTime = time.Date(2021, 8, 30, 15, 0, 0, 0, time.UTC)
|
||||||
ChainID = "kava-8"
|
ChainID = "kava-8"
|
||||||
// TODO: update SWP reward per second amount before production
|
// TODO: update SWP reward per second amount before production
|
||||||
// TODO: add swap tokens to kavadist module account
|
// TODO: add swap tokens to kavadist module account
|
||||||
@ -59,6 +64,14 @@ func MigrateAppState(v0_14AppState genutil.AppMap) {
|
|||||||
v0_14Codec := makeV014Codec()
|
v0_14Codec := makeV014Codec()
|
||||||
v0_15Codec := app.MakeCodec()
|
v0_15Codec := app.MakeCodec()
|
||||||
|
|
||||||
|
// Migrate auth app state
|
||||||
|
if v0_14AppState[auth.ModuleName] != nil {
|
||||||
|
var authGenState auth.GenesisState
|
||||||
|
v0_14Codec.MustUnmarshalJSON(v0_14AppState[auth.ModuleName], &authGenState)
|
||||||
|
delete(v0_14AppState, auth.ModuleName)
|
||||||
|
v0_14AppState[auth.ModuleName] = v0_15Codec.MustMarshalJSON(Auth(authGenState, GenesisTime))
|
||||||
|
}
|
||||||
|
|
||||||
// Migrate incentive app state
|
// Migrate incentive app state
|
||||||
if v0_14AppState[v0_14incentive.ModuleName] != nil {
|
if v0_14AppState[v0_14incentive.ModuleName] != nil {
|
||||||
var incentiveGenState v0_14incentive.GenesisState
|
var incentiveGenState v0_14incentive.GenesisState
|
||||||
@ -83,11 +96,28 @@ func MigrateAppState(v0_14AppState genutil.AppMap) {
|
|||||||
func makeV014Codec() *codec.Codec {
|
func makeV014Codec() *codec.Codec {
|
||||||
cdc := codec.New()
|
cdc := codec.New()
|
||||||
sdk.RegisterCodec(cdc)
|
sdk.RegisterCodec(cdc)
|
||||||
|
cryptoAmino.RegisterAmino(cdc)
|
||||||
|
auth.RegisterCodec(cdc)
|
||||||
|
supply.RegisterCodec(cdc)
|
||||||
|
vesting.RegisterCodec(cdc)
|
||||||
|
v0_14validator_vesting.RegisterCodec(cdc)
|
||||||
v0_14committee.RegisterCodec(cdc)
|
v0_14committee.RegisterCodec(cdc)
|
||||||
v0_14incentive.RegisterCodec(cdc)
|
v0_14incentive.RegisterCodec(cdc)
|
||||||
return cdc
|
return cdc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Auth migrates the auth genesis state to a new state with pruned vesting periods
|
||||||
|
func Auth(genesisState auth.GenesisState, genesisTime time.Time) auth.GenesisState {
|
||||||
|
accounts := make([]authexported.GenesisAccount, len(genesisState.Accounts))
|
||||||
|
migratedGenesisState := auth.NewGenesisState(genesisState.Params, accounts)
|
||||||
|
|
||||||
|
for i, acc := range genesisState.Accounts {
|
||||||
|
accounts[i] = authexported.GenesisAccount(MigrateAccount(acc, genesisTime))
|
||||||
|
}
|
||||||
|
|
||||||
|
return migratedGenesisState
|
||||||
|
}
|
||||||
|
|
||||||
// Committee migrates from a v0.14 committee genesis state to a v0.15 committee genesis state
|
// Committee migrates from a v0.14 committee genesis state to a v0.15 committee genesis state
|
||||||
func Committee(genesisState v0_14committee.GenesisState) v0_15committee.GenesisState {
|
func Committee(genesisState v0_14committee.GenesisState) v0_15committee.GenesisState {
|
||||||
|
|
||||||
|
@ -5,11 +5,15 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth/vesting"
|
||||||
"github.com/cosmos/cosmos-sdk/x/genutil"
|
"github.com/cosmos/cosmos-sdk/x/genutil"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/kava-labs/kava/app"
|
"github.com/kava-labs/kava/app"
|
||||||
@ -99,3 +103,94 @@ func TestIncentive(t *testing.T) {
|
|||||||
|
|
||||||
require.JSONEq(t, string(bz), string(appState[v0_15incentive.ModuleName]))
|
require.JSONEq(t, string(bz), string(appState[v0_15incentive.ModuleName]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compare migration against auto-generated snapshot to catch regressions
|
||||||
|
func TestAuth_Snapshot(t *testing.T) {
|
||||||
|
bz, err := ioutil.ReadFile(filepath.Join("testdata", "kava-7-test-auth-state.json"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
appState := genutil.AppMap{auth.ModuleName: bz}
|
||||||
|
|
||||||
|
MigrateAppState(appState)
|
||||||
|
|
||||||
|
if _, err := os.Stat(filepath.Join("testdata", "kava-8-test-auth-state.json")); os.IsNotExist(err) {
|
||||||
|
err := ioutil.WriteFile(filepath.Join("testdata", "kava-8-test-auth-state.json"), appState[auth.ModuleName], 0644)
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshot, err := ioutil.ReadFile(filepath.Join("testdata", "kava-8-test-auth-state.json"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.JSONEq(t, string(snapshot), string(appState[auth.ModuleName]), "expected auth state snapshot to be equal")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAuth_ParametersEqual(t *testing.T) {
|
||||||
|
bz, err := ioutil.ReadFile(filepath.Join("testdata", "kava-7-test-auth-state.json"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var genesisState auth.GenesisState
|
||||||
|
cdc := app.MakeCodec()
|
||||||
|
cdc.MustUnmarshalJSON(bz, &genesisState)
|
||||||
|
|
||||||
|
migratedGenesisState := Auth(genesisState, GenesisTime)
|
||||||
|
|
||||||
|
assert.Equal(t, genesisState.Params, migratedGenesisState.Params, "expected auth parameters to not change")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAuth_AccountConversion(t *testing.T) {
|
||||||
|
bz, err := ioutil.ReadFile(filepath.Join("testdata", "kava-7-test-auth-state.json"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var genesisState auth.GenesisState
|
||||||
|
cdc := app.MakeCodec()
|
||||||
|
cdc.MustUnmarshalJSON(bz, &genesisState)
|
||||||
|
|
||||||
|
migratedGenesisState := Auth(genesisState, GenesisTime)
|
||||||
|
require.Equal(t, len(genesisState.Accounts), len(migratedGenesisState.Accounts), "expected the number of accounts after migration to be equal")
|
||||||
|
err = auth.ValidateGenesis(migratedGenesisState)
|
||||||
|
require.NoError(t, err, "expected migrated genesis to be valid")
|
||||||
|
|
||||||
|
for i, acc := range migratedGenesisState.Accounts {
|
||||||
|
oldAcc := genesisState.Accounts[i]
|
||||||
|
|
||||||
|
// total owned coins does not change
|
||||||
|
require.Equal(t, oldAcc.GetCoins(), acc.GetCoins(), "expected base coins to not change")
|
||||||
|
|
||||||
|
// ensure spenable coins at genesis time is equal
|
||||||
|
require.Equal(t, oldAcc.SpendableCoins(GenesisTime), acc.SpendableCoins(GenesisTime), "expected spendable coins to not change")
|
||||||
|
// check 30 days
|
||||||
|
futureDate := GenesisTime.Add(30 * 24 * time.Hour)
|
||||||
|
require.Equal(t, oldAcc.SpendableCoins(futureDate), acc.SpendableCoins(futureDate), "expected spendable coins to not change")
|
||||||
|
// check 90 days
|
||||||
|
futureDate = GenesisTime.Add(90 * 24 * time.Hour)
|
||||||
|
require.Equal(t, oldAcc.SpendableCoins(futureDate), acc.SpendableCoins(futureDate), "expected spendable coins to not change")
|
||||||
|
// check 180 days
|
||||||
|
futureDate = GenesisTime.Add(180 * 24 * time.Hour)
|
||||||
|
require.Equal(t, oldAcc.SpendableCoins(futureDate), acc.SpendableCoins(futureDate), "expected spendable coins to not change")
|
||||||
|
// check 365 days
|
||||||
|
futureDate = GenesisTime.Add(365 * 24 * time.Hour)
|
||||||
|
require.Equal(t, oldAcc.SpendableCoins(futureDate), acc.SpendableCoins(futureDate), "expected spendable coins to not change")
|
||||||
|
|
||||||
|
if vacc, ok := acc.(*vesting.PeriodicVestingAccount); ok {
|
||||||
|
// old account must be a periodic vesting account
|
||||||
|
oldVacc, ok := oldAcc.(*vesting.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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
1
migrate/v0_15/testdata/kava-7-test-auth-state.json
vendored
Normal file
1
migrate/v0_15/testdata/kava-7-test-auth-state.json
vendored
Normal file
File diff suppressed because one or more lines are too long
1
migrate/v0_15/testdata/kava-8-test-auth-state.json
vendored
Normal file
1
migrate/v0_15/testdata/kava-8-test-auth-state.json
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user