Merge PR #3308: Genesis Vesting Accounts & Simulation
* Update vesting spec and impl time fields and constructors * Update genesis to support vesting accounts * More spec and godoc updates * Update genesis section in vesting spec * Fix bank unit tests * Add test cases to ToAccount in genesis * Update RegisterCodec to include vesting interface and types * Fix GetVestedCoins bug where block time is past vesting end time * Add vesting accounts to simulation * Update vesting genesis logic to panic on invalid accounts * Change randomness of vesting accounts in simulation
This commit is contained in:
committed by
Christopher Goes
parent
20bcacfaf4
commit
f2e87ad81f
+2
-1
@@ -231,10 +231,11 @@ func (app *GaiaApp) initFromGenesisState(ctx sdk.Context, genesisState GenesisSt
|
||||
sort.Slice(genesisState.Accounts, func(i, j int) bool {
|
||||
return genesisState.Accounts[i].AccountNumber < genesisState.Accounts[j].AccountNumber
|
||||
})
|
||||
|
||||
// load the accounts
|
||||
for _, gacc := range genesisState.Accounts {
|
||||
acc := gacc.ToAccount()
|
||||
acc.AccountNumber = app.accountKeeper.GetNextAccountNumber(ctx)
|
||||
acc = app.accountKeeper.NewAccount(ctx, acc) // set account number
|
||||
app.accountKeeper.SetAccount(ctx, acc)
|
||||
}
|
||||
|
||||
|
||||
+32
-5
@@ -58,12 +58,15 @@ func NewGenesisState(accounts []GenesisAccount, authData auth.GenesisState,
|
||||
}
|
||||
}
|
||||
|
||||
// nolint
|
||||
// GenesisAccount defines an account initialized at genesis.
|
||||
type GenesisAccount struct {
|
||||
Address sdk.AccAddress `json:"address"`
|
||||
Coins sdk.Coins `json:"coins"`
|
||||
Sequence uint64 `json:"sequence_number"`
|
||||
AccountNumber uint64 `json:"account_number"`
|
||||
Vesting bool `json:"vesting"`
|
||||
StartTime int64 `json:"start_time"`
|
||||
EndTime int64 `json:"end_time"`
|
||||
}
|
||||
|
||||
func NewGenesisAccount(acc *auth.BaseAccount) GenesisAccount {
|
||||
@@ -76,22 +79,43 @@ func NewGenesisAccount(acc *auth.BaseAccount) GenesisAccount {
|
||||
}
|
||||
|
||||
func NewGenesisAccountI(acc auth.Account) GenesisAccount {
|
||||
return GenesisAccount{
|
||||
gacc := GenesisAccount{
|
||||
Address: acc.GetAddress(),
|
||||
Coins: acc.GetCoins(),
|
||||
AccountNumber: acc.GetAccountNumber(),
|
||||
Sequence: acc.GetSequence(),
|
||||
}
|
||||
|
||||
vacc, ok := acc.(auth.VestingAccount)
|
||||
if ok {
|
||||
gacc.Vesting = true
|
||||
gacc.StartTime = vacc.GetStartTime()
|
||||
gacc.EndTime = vacc.GetEndTime()
|
||||
}
|
||||
|
||||
return gacc
|
||||
}
|
||||
|
||||
// convert GenesisAccount to auth.BaseAccount
|
||||
func (ga *GenesisAccount) ToAccount() (acc *auth.BaseAccount) {
|
||||
return &auth.BaseAccount{
|
||||
func (ga *GenesisAccount) ToAccount() auth.Account {
|
||||
bacc := &auth.BaseAccount{
|
||||
Address: ga.Address,
|
||||
Coins: ga.Coins.Sort(),
|
||||
AccountNumber: ga.AccountNumber,
|
||||
Sequence: ga.Sequence,
|
||||
}
|
||||
|
||||
if ga.Vesting {
|
||||
if ga.StartTime != 0 && ga.EndTime != 0 {
|
||||
return auth.NewContinuousVestingAccount(bacc, ga.StartTime, ga.EndTime)
|
||||
} else if ga.EndTime != 0 {
|
||||
return auth.NewDelayedVestingAccount(bacc, ga.EndTime)
|
||||
} else {
|
||||
panic(fmt.Sprintf("invalid genesis vesting account: %+v", ga))
|
||||
}
|
||||
}
|
||||
|
||||
return bacc
|
||||
}
|
||||
|
||||
// Create the core parameters for genesis initialization for gaia
|
||||
@@ -114,11 +138,13 @@ func GaiaAppGenState(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs []js
|
||||
if err := cdc.UnmarshalJSON(genTx, &tx); err != nil {
|
||||
return genesisState, err
|
||||
}
|
||||
|
||||
msgs := tx.GetMsgs()
|
||||
if len(msgs) != 1 {
|
||||
return genesisState, errors.New(
|
||||
"must provide genesis StdTx with exactly 1 CreateValidator message")
|
||||
}
|
||||
|
||||
if _, ok := msgs[0].(staking.MsgCreateValidator); !ok {
|
||||
return genesisState, fmt.Errorf(
|
||||
"Genesis transaction %v does not contain a MsgCreateValidator", i)
|
||||
@@ -126,7 +152,6 @@ func GaiaAppGenState(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs []js
|
||||
}
|
||||
|
||||
for _, acc := range genesisState.Accounts {
|
||||
// create the genesis account, give'm few steaks and a buncha token with there name
|
||||
for _, coin := range acc.Coins {
|
||||
if coin.Denom == bondDenom {
|
||||
stakingData.Pool.LooseTokens = stakingData.Pool.LooseTokens.
|
||||
@@ -134,8 +159,10 @@ func GaiaAppGenState(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs []js
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
genesisState.StakingData = stakingData
|
||||
genesisState.GenTxs = appGenTxs
|
||||
|
||||
return genesisState, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package app
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto/secp256k1"
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
@@ -56,7 +57,17 @@ func TestToAccount(t *testing.T) {
|
||||
addr := sdk.AccAddress(priv.PubKey().Address())
|
||||
authAcc := auth.NewBaseAccountWithAddress(addr)
|
||||
genAcc := NewGenesisAccount(&authAcc)
|
||||
require.Equal(t, authAcc, *genAcc.ToAccount())
|
||||
acc := genAcc.ToAccount()
|
||||
require.IsType(t, &auth.BaseAccount{}, acc)
|
||||
require.Equal(t, &authAcc, acc.(*auth.BaseAccount))
|
||||
|
||||
vacc := auth.NewContinuousVestingAccount(
|
||||
&authAcc, time.Now().Unix(), time.Now().Add(24*time.Hour).Unix(),
|
||||
)
|
||||
genAcc = NewGenesisAccountI(vacc)
|
||||
acc = genAcc.ToAccount()
|
||||
require.IsType(t, &auth.ContinuousVestingAccount{}, acc)
|
||||
require.Equal(t, vacc, acc.(*auth.ContinuousVestingAccount))
|
||||
}
|
||||
|
||||
func TestGaiaAppGenTx(t *testing.T) {
|
||||
|
||||
@@ -54,7 +54,7 @@ func init() {
|
||||
flag.IntVar(&period, "SimulationPeriod", 1, "Run slow invariants only once every period assertions")
|
||||
}
|
||||
|
||||
func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage {
|
||||
func appStateFn(r *rand.Rand, accs []simulation.Account, genesisTimestamp time.Time) json.RawMessage {
|
||||
var genesisAccounts []GenesisAccount
|
||||
|
||||
amount := int64(r.Intn(1e6))
|
||||
@@ -67,13 +67,44 @@ func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage {
|
||||
"\t{amount of steak per account: %v, initially bonded validators: %v}\n",
|
||||
amount, numInitiallyBonded)
|
||||
|
||||
// Randomly generate some genesis accounts
|
||||
for _, acc := range accs {
|
||||
// randomly generate some genesis accounts
|
||||
for i, acc := range accs {
|
||||
coins := sdk.Coins{sdk.NewCoin(stakingTypes.DefaultBondDenom, sdk.NewInt(amount))}
|
||||
genesisAccounts = append(genesisAccounts, GenesisAccount{
|
||||
Address: acc.Address,
|
||||
Coins: coins,
|
||||
})
|
||||
bacc := auth.NewBaseAccountWithAddress(acc.Address)
|
||||
bacc.SetCoins(coins)
|
||||
|
||||
var gacc GenesisAccount
|
||||
|
||||
// Only consider making a vesting account once the initial bonded validator
|
||||
// set is exhausted due to needing to track DelegatedVesting.
|
||||
if int64(i) > numInitiallyBonded && r.Intn(100) < 50 {
|
||||
var (
|
||||
vacc auth.VestingAccount
|
||||
endTime int
|
||||
)
|
||||
|
||||
startTime := genesisTimestamp.Unix()
|
||||
|
||||
// Allow for some vesting accounts to vest very quickly while others very
|
||||
// slowly.
|
||||
if r.Intn(100) < 50 {
|
||||
endTime = randIntBetween(r, int(startTime), int(startTime+(60*60*24*30)))
|
||||
} else {
|
||||
endTime = randIntBetween(r, int(startTime), int(startTime+(60*60*12)))
|
||||
}
|
||||
|
||||
if r.Intn(100) < 50 {
|
||||
vacc = auth.NewContinuousVestingAccount(&bacc, startTime, int64(endTime))
|
||||
} else {
|
||||
vacc = auth.NewDelayedVestingAccount(&bacc, int64(endTime))
|
||||
}
|
||||
|
||||
gacc = NewGenesisAccountI(vacc)
|
||||
} else {
|
||||
gacc = NewGenesisAccount(&bacc)
|
||||
}
|
||||
|
||||
genesisAccounts = append(genesisAccounts, gacc)
|
||||
}
|
||||
|
||||
authGenesis := auth.GenesisState{
|
||||
@@ -156,6 +187,7 @@ func appStateFn(r *rand.Rand, accs []simulation.Account) json.RawMessage {
|
||||
validators = append(validators, validator)
|
||||
delegations = append(delegations, delegation)
|
||||
}
|
||||
|
||||
stakingGenesis.Pool.LooseTokens = sdk.NewInt((amount * numAccs) + (numInitiallyBonded * amount))
|
||||
stakingGenesis.Validators = validators
|
||||
stakingGenesis.Bonds = delegations
|
||||
|
||||
Reference in New Issue
Block a user