Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

R4R: Fix state export/import, add to CI #2690

Merged
merged 34 commits into from
Nov 9, 2018
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
766c3b0
Update PENDING.md
cwgoes Nov 5, 2018
f20e961
Update slashing import/export
cwgoes Nov 5, 2018
85a6d88
More slashing.WriteGenesis
cwgoes Nov 5, 2018
7c88bb6
Add test import/export to CI
cwgoes Nov 5, 2018
0545e18
Efficacious import/export
cwgoes Nov 5, 2018
40fa0fd
Store equality comparision in progress
cwgoes Nov 5, 2018
ca6c0fc
Account stores match
cwgoes Nov 5, 2018
5ac2359
Onto debugging x/stake store
cwgoes Nov 5, 2018
145435f
'make format'
cwgoes Nov 5, 2018
54b9129
Fix validator bond intra-tx counter
cwgoes Nov 6, 2018
41088c4
Set timeslices for unbonding validators
cwgoes Nov 6, 2018
84e5514
Fix missed blocks
cwgoes Nov 6, 2018
c7c21ad
Fix distribution import/export
cwgoes Nov 6, 2018
ed6866a
x/gov fixes in progress
cwgoes Nov 6, 2018
4eaffaf
Fee collection keeper import/export
cwgoes Nov 6, 2018
76cb763
Switch seed to realize more discrepancies
cwgoes Nov 6, 2018
0ecc430
x/stake import/export contd...
cwgoes Nov 6, 2018
80601a6
Linter fix
cwgoes Nov 6, 2018
699f813
Fix dependancy issue
jackzampolin Nov 7, 2018
b354738
Update lockfile
jackzampolin Nov 7, 2018
dcaa533
Merge branch 'develop' into cwgoes/state-export-import-fixes
cwgoes Nov 7, 2018
f508536
Peek, don't update proposal ID
cwgoes Nov 7, 2018
0dcce00
Failing case (works on seeds 12, 13 now)
cwgoes Nov 7, 2018
5365ba1
WriteGenesis => ExportGenesis
cwgoes Nov 7, 2018
257ace9
Address remaining @jaekwon comments
cwgoes Nov 7, 2018
252d961
Works but still need to debug stake, test gov
cwgoes Nov 7, 2018
ba21c55
Delete validators from unbonding queue when re-bonded
cwgoes Nov 7, 2018
6e0948e
Failing again
cwgoes Nov 7, 2018
9a4bde0
Hook for validator deletion, fix staking genesis tests
cwgoes Nov 7, 2018
9c7cfe7
Swap to use hooks for add/remove pubkey
cwgoes Nov 8, 2018
306a6bd
Cleanup, fails again
cwgoes Nov 8, 2018
2b18c7f
More testing seeds
cwgoes Nov 8, 2018
1814284
Bug fixes!
cwgoes Nov 8, 2018
1567057
Fixup hooks
cwgoes Nov 8, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,24 @@ jobs:
export PATH="$GOBIN:$PATH"
make test_sim_gaia_fast

test_sim_gaia_import_export:
<<: *defaults
parallelism: 1
steps:
- attach_workspace:
at: /tmp/workspace
- checkout
- run:
name: dependencies
command: |
export PATH="$GOBIN:$PATH"
make get_vendor_deps
- run:
name: Test Gaia import/export simulation
command: |
export PATH="$GOBIN:$PATH"
make test_sim_gaia_import_export

test_sim_gaia_multi_seed:
<<: *defaults
parallelism: 1
Expand Down Expand Up @@ -259,6 +277,9 @@ workflows:
- test_sim_gaia_fast:
requires:
- setup_dependencies
- test_sim_gaia_import_export:
requires:
- setup_dependencies
- test_sim_gaia_multi_seed:
requires:
- setup_dependencies
Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,10 @@ test_sim_gaia_fast:
@echo "Running quick Gaia simulation. This may take several minutes..."
@go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=500 -SimulationBlockSize=200 -SimulationCommit=true -SimulationSeed=10 -v -timeout 24h

test_sim_gaia_import_export:
@echo "Running Gaia import/export simulation. This may take several minutes..."
@go test ./cmd/gaia/app -run TestGaiaImportExport -SimulationEnabled=true -SimulationNumBlocks=50 -SimulationBlockSize=200 -SimulationCommit=true -SimulationSeed=12 -v -timeout 24h

test_sim_gaia_multi_seed:
@echo "Running multi-seed Gaia simulation. This may take awhile!"
@bash scripts/multisim.sh 25
Expand Down
3 changes: 2 additions & 1 deletion PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ FEATURES
* Gaia

* SDK
* (#1336) Mechanism for SDK Users to configure their own Bech32 prefixes instead of using the default cosmos prefixes.
- \#1336 Mechanism for SDK Users to configure their own Bech32 prefixes instead of using the default cosmos prefixes.

* Tendermint

Expand Down Expand Up @@ -63,6 +63,7 @@ BUG FIXES

* Gaia
- \#2670 [x/stake] fixed incorrent `IterateBondedValidators` and split into two functions: `IterateBondedValidators` and `IterateLastBlockConsValidators`
- \#2648 [gaiad] Fix `gaiad export` / `gaiad import` consistency, test in CI

* SDK
- \#2625 [x/gov] fix AppendTag function usage error
Expand Down
8 changes: 7 additions & 1 deletion cmd/gaia/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,10 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci
// return sdk.ErrGenesisParse("").TraceCause(err, "")
}

// sort by account number to maintain consistency
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()
Expand All @@ -245,6 +249,7 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci
}

// load the address to pubkey map
auth.InitGenesis(ctx, app.feeCollectionKeeper, genesisState.AuthData)
slashing.InitGenesis(ctx, app.slashingKeeper, genesisState.SlashingData, genesisState.StakeData)
gov.InitGenesis(ctx, app.govKeeper, genesisState.GovData)
mint.InitGenesis(ctx, app.mintKeeper, genesisState.MintData)
Expand Down Expand Up @@ -306,11 +311,12 @@ func (app *GaiaApp) ExportAppStateAndValidators() (appState json.RawMessage, val
app.accountKeeper.IterateAccounts(ctx, appendAccount)
genState := NewGenesisState(
accounts,
auth.WriteGenesis(ctx, app.feeCollectionKeeper),
stake.WriteGenesis(ctx, app.stakeKeeper),
mint.WriteGenesis(ctx, app.mintKeeper),
distr.WriteGenesis(ctx, app.distrKeeper),
gov.WriteGenesis(ctx, app.govKeeper),
slashing.GenesisState{}, // TODO create write methods
slashing.WriteGenesis(ctx, app.slashingKeeper),
)
appState, err = codec.MarshalJSONIndent(app.cdc, genState)
if err != nil {
Expand Down
30 changes: 20 additions & 10 deletions cmd/gaia/app/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ var (
// State to Unmarshal
type GenesisState struct {
Accounts []GenesisAccount `json:"accounts"`
AuthData auth.GenesisState `json:"auth"`
StakeData stake.GenesisState `json:"stake"`
MintData mint.GenesisState `json:"mint"`
DistrData distr.GenesisState `json:"distr"`
Expand All @@ -40,11 +41,12 @@ type GenesisState struct {
GenTxs []json.RawMessage `json:"gentxs"`
}

func NewGenesisState(accounts []GenesisAccount, stakeData stake.GenesisState, mintData mint.GenesisState,
func NewGenesisState(accounts []GenesisAccount, authData auth.GenesisState, stakeData stake.GenesisState, mintData mint.GenesisState,
distrData distr.GenesisState, govData gov.GenesisState, slashingData slashing.GenesisState) GenesisState {

return GenesisState{
Accounts: accounts,
AuthData: authData,
StakeData: stakeData,
MintData: mintData,
DistrData: distrData,
Expand All @@ -53,31 +55,39 @@ func NewGenesisState(accounts []GenesisAccount, stakeData stake.GenesisState, mi
}
}

// GenesisAccount doesn't need pubkey or sequence
// nolint
type GenesisAccount struct {
Address sdk.AccAddress `json:"address"`
Coins sdk.Coins `json:"coins"`
Address sdk.AccAddress `json:"address"`
Coins sdk.Coins `json:"coins"`
Sequence int64 `json:"sequence_number"`
AccountNumber int64 `json:"account_number"`
}

func NewGenesisAccount(acc *auth.BaseAccount) GenesisAccount {
return GenesisAccount{
Address: acc.Address,
Coins: acc.Coins,
Address: acc.Address,
Coins: acc.Coins,
AccountNumber: acc.AccountNumber,
Sequence: acc.Sequence,
}
}

func NewGenesisAccountI(acc auth.Account) GenesisAccount {
return GenesisAccount{
Address: acc.GetAddress(),
Coins: acc.GetCoins(),
Address: acc.GetAddress(),
Coins: acc.GetCoins(),
AccountNumber: acc.GetAccountNumber(),
Sequence: acc.GetSequence(),
}
}

// convert GenesisAccount to auth.BaseAccount
func (ga *GenesisAccount) ToAccount() (acc *auth.BaseAccount) {
return &auth.BaseAccount{
Address: ga.Address,
Coins: ga.Coins.Sort(),
Address: ga.Address,
Coins: ga.Coins.Sort(),
AccountNumber: ga.AccountNumber,
Sequence: ga.Sequence,
}
}

Expand Down
2 changes: 1 addition & 1 deletion cmd/gaia/app/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func makeMsg(name string, pk crypto.PubKey) auth.StdTx {
desc := stake.NewDescription(name, "", "", "")
comm := stakeTypes.CommissionMsg{}
msg := stake.NewMsgCreateValidator(sdk.ValAddress(pk.Address()), pk, sdk.NewInt64Coin(bondDenom,
50), desc, comm)
50), desc, comm)
return auth.NewStdTx([]sdk.Msg{msg}, auth.StdFee{}, nil, "")
}

Expand Down
85 changes: 85 additions & 0 deletions cmd/gaia/app/sim_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

"github.com/stretchr/testify/require"

abci "github.com/tendermint/tendermint/abci/types"
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/libs/log"

Expand Down Expand Up @@ -266,6 +267,90 @@ func TestFullGaiaSimulation(t *testing.T) {
require.Nil(t, err)
}

func TestGaiaImportExport(t *testing.T) {
if !enabled {
t.Skip("Skipping Gaia import/export simulation")
}

// Setup Gaia application
var logger log.Logger
if verbose {
logger = log.TestingLogger()
} else {
logger = log.NewNopLogger()
}
var db dbm.DB
dir, _ := ioutil.TempDir("", "goleveldb-gaia-sim")
db, _ = dbm.NewGoLevelDB("Simulation", dir)
defer func() {
db.Close()
os.RemoveAll(dir)
}()
app := NewGaiaApp(logger, db, nil)
require.Equal(t, "GaiaApp", app.Name())

// Run randomized simulation
err := simulation.SimulateFromSeed(
t, app.BaseApp, appStateFn, seed,
testAndRunTxs(app),
[]simulation.RandSetup{},
invariants(app),
numBlocks,
blockSize,
commit,
)
if commit {
// for memdb:
// fmt.Println("Database Size", db.Stats()["database.size"])
fmt.Println("GoLevelDB Stats")
fmt.Println(db.Stats()["leveldb.stats"])
fmt.Println("GoLevelDB cached block size", db.Stats()["leveldb.cachedblock"])
}
require.Nil(t, err)

fmt.Printf("Exporting genesis...\n")

appState, _, err := app.ExportAppStateAndValidators()
if err != nil {
panic(err)
}

fmt.Printf("Importing genesis...\n")

newDir, _ := ioutil.TempDir("", "goleveldb-gaia-sim-2")
newDB, _ := dbm.NewGoLevelDB("Simulation-2", dir)
defer func() {
newDB.Close()
os.RemoveAll(newDir)
}()
newApp := NewGaiaApp(log.NewNopLogger(), newDB, nil)
require.Equal(t, "GaiaApp", newApp.Name())
request := abci.RequestInitChain{
AppStateBytes: appState,
}
newApp.InitChain(request)
newApp.Commit()

fmt.Printf("Comparing stores...\n")
ctxA := app.NewContext(true, abci.Header{})
ctxB := newApp.NewContext(true, abci.Header{})
storeKeysA := []sdk.StoreKey{app.keyMain, app.keyAccount, app.keyStake, app.keySlashing,
app.keyMint, app.keyDistr, app.keyFeeCollection, app.keyParams, app.keyGov}
storeKeysB := []sdk.StoreKey{newApp.keyMain, newApp.keyAccount, newApp.keyStake, newApp.keySlashing,
newApp.keyMint, newApp.keyDistr, newApp.keyFeeCollection, newApp.keyParams, newApp.keyGov}
require.Equal(t, len(storeKeysA), len(storeKeysB))
for index, storeKeyA := range storeKeysA {
storeKeyB := storeKeysB[index]
storeA := ctxA.KVStore(storeKeyA)
storeB := ctxB.KVStore(storeKeyB)
kvA, kvB, count, equal := sdk.DiffKVStores(storeA, storeB)
fmt.Printf("Compared %d key/value pairs between %s and %s\n", count, storeKeyA, storeKeyB)
require.True(t, equal, "unequal stores: %s / %s:\nstore A %s (%X) => %s (%X)\nstore B %s (%X) => %s (%X)",
storeKeyA, storeKeyB, kvA.Key, kvA.Key, kvA.Value, kvA.Value, kvB.Key, kvB.Key, kvB.Value, kvB.Value)
}

}

// TODO: Make another test for the fuzzer itself, which just has noOp txs
// and doesn't depend on gaia
func TestAppStateDeterminism(t *testing.T) {
Expand Down
28 changes: 28 additions & 0 deletions types/store.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package types

import (
"bytes"
"fmt"
"io"

Expand Down Expand Up @@ -176,6 +177,33 @@ func KVStoreReversePrefixIterator(kvs KVStore, prefix []byte) Iterator {
return kvs.ReverseIterator(prefix, PrefixEndBytes(prefix))
}

// Compare two KVstores, return either the first key/value pair
// at which they differ and whether or not they are equal
func DiffKVStores(a KVStore, b KVStore) (kvA cmn.KVPair, kvB cmn.KVPair, count int64, equal bool) {
iterA := a.Iterator(nil, nil)
iterB := b.Iterator(nil, nil)
count = int64(0)
for {
if !iterA.Valid() && !iterB.Valid() {
break
}
var kvA, kvB cmn.KVPair
if iterA.Valid() {
kvA = cmn.KVPair{Key: iterA.Key(), Value: iterA.Value()}
}
if iterB.Valid() {
kvB = cmn.KVPair{Key: iterB.Key(), Value: iterB.Value()}
}
if !bytes.Equal(kvA.Key, kvB.Key) || !bytes.Equal(kvA.Value, kvB.Value) {
return kvA, kvB, count, false
}
iterA.Next()
iterB.Next()
count++
}
return cmn.KVPair{}, cmn.KVPair{}, count, true
}

// CacheKVStore cache-wraps a KVStore. After calling .Write() on
// the CacheKVStore, all previously created CacheKVStores on the
// object expire.
Expand Down
33 changes: 33 additions & 0 deletions x/auth/genesis.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package auth

import (
sdk "github.com/cosmos/cosmos-sdk/types"
)

// GenesisState - all auth state that must be provided at genesis
type GenesisState struct {
CollectedFees sdk.Coins `json:"collected_fees"` // collected fees
}

// Create a new genesis state
func NewGenesisState(collectedFees sdk.Coins) GenesisState {
return GenesisState{
CollectedFees: collectedFees,
}
}

// Return a default genesis state
func DefaultGenesisState() GenesisState {
return NewGenesisState(sdk.Coins{})
}

// Init store state from genesis data
func InitGenesis(ctx sdk.Context, keeper FeeCollectionKeeper, data GenesisState) {
keeper.setCollectedFees(ctx, data.CollectedFees)
}

// WriteGenesis returns a GenesisState for a given context and keeper
func WriteGenesis(ctx sdk.Context, keeper FeeCollectionKeeper) GenesisState {
cwgoes marked this conversation as resolved.
Show resolved Hide resolved
collectedFees := keeper.GetCollectedFees(ctx)
return NewGenesisState(collectedFees)
}
File renamed without changes.
File renamed without changes.
4 changes: 3 additions & 1 deletion x/distribution/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) {
for _, dw := range data.DelegatorWithdrawInfos {
keeper.SetDelegatorWithdrawAddr(ctx, dw.DelegatorAddr, dw.WithdrawAddr)
}
keeper.SetPreviousProposerConsAddr(ctx, data.PreviousProposer)
}

// WriteGenesis returns a GenesisState for a given context and keeper. The
Expand All @@ -33,6 +34,7 @@ func WriteGenesis(ctx sdk.Context, keeper Keeper) types.GenesisState {
vdis := keeper.GetAllValidatorDistInfos(ctx)
ddis := keeper.GetAllDelegationDistInfos(ctx)
dwis := keeper.GetAllDelegatorWithdrawInfos(ctx)
pp := keeper.GetPreviousProposerConsAddr(ctx)
return NewGenesisState(feePool, communityTax, baseProposerRewards,
bonusProposerRewards, vdis, ddis, dwis)
bonusProposerRewards, vdis, ddis, dwis, pp)
}
4 changes: 2 additions & 2 deletions x/distribution/keeper/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ func (k Keeper) GetAllDelegationDistInfos(ctx sdk.Context) (ddis []types.Delegat
// Get the set of all delegator-withdraw addresses with no limits, used during genesis dump
func (k Keeper) GetAllDelegatorWithdrawInfos(ctx sdk.Context) (dwis []types.DelegatorWithdrawInfo) {
store := ctx.KVStore(k.storeKey)
iterator := sdk.KVStorePrefixIterator(store, DelegationDistInfoKey)
iterator := sdk.KVStorePrefixIterator(store, DelegatorWithdrawInfoKey)
defer iterator.Close()

for ; iterator.Valid(); iterator.Next() {
dw := types.DelegatorWithdrawInfo{
DelegatorAddr: sdk.AccAddress(iterator.Key()),
DelegatorAddr: sdk.AccAddress(iterator.Key()[1:]),
cwgoes marked this conversation as resolved.
Show resolved Hide resolved
WithdrawAddr: sdk.AccAddress(iterator.Value()),
}
dwis = append(dwis, dw)
Expand Down
Loading