Skip to content
This repository has been archived by the owner on Nov 16, 2022. It is now read-only.

Commit

Permalink
Merge pull request #3291 from bandprotocol/nathachai/export-genesis-l…
Browse files Browse the repository at this point in the history
…aozi

Improve export genesis for oracle module to include more information
  • Loading branch information
taobun authored Apr 20, 2021
2 parents 069954f + a718566 commit bc58a72
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 5 deletions.
17 changes: 17 additions & 0 deletions chain/app/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,18 @@ func (app *BandApp) ExportAppStateAndValidators(forZeroHeight bool, jailWhiteLis
ctx := app.NewContext(true, abci.Header{Height: app.LastBlockHeight()})

if forZeroHeight {
ctx.Logger().Info("Preparing state for zero-height genesis")
app.prepForZeroHeightGenesis(ctx, jailWhiteList)
}

ctx.Logger().Info("Begin exporting states from each module")
genState := app.mm.ExportGenesis(ctx)
ctx.Logger().Info("Encode exported states to JSON")
appState, err = codec.MarshalJSONIndent(app.cdc, genState)
if err != nil {
return nil, nil, err
}
ctx.Logger().Info("Writing validators for the genesis")
validators = staking.WriteValidators(ctx, app.StakingKeeper)
return appState, validators, nil
}
Expand All @@ -54,11 +58,13 @@ func (app *BandApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList []st
}

/* Just to be safe, assert the invariants on current state. */
ctx.Logger().Info("Asserting invarient")
app.CrisisKeeper.AssertInvariants(ctx)

/* Handle fee distribution state. */

// withdraw all validator commission
ctx.Logger().Info("Withdraw all validator commission")
app.StakingKeeper.IterateValidators(ctx, func(_ int64, val staking.ValidatorI) (stop bool) {
accumCommission := app.DistrKeeper.GetValidatorAccumulatedCommission(ctx, val.GetOperator())
if accumCommission.IsZero() {
Expand All @@ -72,6 +78,7 @@ func (app *BandApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList []st
})

// withdraw all delegator rewards
ctx.Logger().Info("Withdraw all delegator rewards")
dels := app.StakingKeeper.GetAllDelegations(ctx)
for _, delegation := range dels {
_, err := app.DistrKeeper.WithdrawDelegationRewards(ctx, delegation.DelegatorAddress, delegation.ValidatorAddress)
Expand All @@ -81,16 +88,20 @@ func (app *BandApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList []st
}

// clear validator slash events
ctx.Logger().Info("Clear all validator slash events")
app.DistrKeeper.DeleteAllValidatorSlashEvents(ctx)

// clear validator historical rewards
ctx.Logger().Info("Clear all validator historical rewards")
app.DistrKeeper.DeleteAllValidatorHistoricalRewards(ctx)

// set context height to zero
ctx.Logger().Info("Set context height to zero")
height := ctx.BlockHeight()
ctx = ctx.WithBlockHeight(0)

// reinitialize all validators
ctx.Logger().Info("Re-Initialize all validators")
app.StakingKeeper.IterateValidators(ctx, func(_ int64, val staking.ValidatorI) (stop bool) {

// donate any unwithdrawn outstanding reward fraction tokens to the community pool
Expand All @@ -104,17 +115,20 @@ func (app *BandApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList []st
})

// reinitialize all delegations
ctx.Logger().Info("Re-Initialize all delegations")
for _, del := range dels {
app.DistrKeeper.Hooks().BeforeDelegationCreated(ctx, del.DelegatorAddress, del.ValidatorAddress)
app.DistrKeeper.Hooks().AfterDelegationModified(ctx, del.DelegatorAddress, del.ValidatorAddress)
}

// reset context height
ctx.Logger().Info("Reset context height")
ctx = ctx.WithBlockHeight(height)

/* Handle staking state. */

// iterate through redelegations, reset creation height
ctx.Logger().Info("Iterate through redelegations, reset creation height")
app.StakingKeeper.IterateRedelegations(ctx, func(_ int64, red staking.Redelegation) (stop bool) {
for i := range red.Entries {
red.Entries[i].CreationHeight = 0
Expand All @@ -124,6 +138,7 @@ func (app *BandApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList []st
})

// iterate through unbonding delegations, reset creation height
ctx.Logger().Info("Iterate through unbonding delegations, reset creation height")
app.StakingKeeper.IterateUnbondingDelegations(ctx, func(_ int64, ubd staking.UnbondingDelegation) (stop bool) {
for i := range ubd.Entries {
ubd.Entries[i].CreationHeight = 0
Expand All @@ -134,6 +149,7 @@ func (app *BandApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList []st

// Iterate through validators by power descending, reset bond heights, and
// update bond intra-tx counters.
ctx.Logger().Info("Iterate through validators by power descending, reset bond heights, and update bond intra-tx counters.")
store := ctx.KVStore(app.keys[staking.StoreKey])
iter := sdk.KVStoreReversePrefixIterator(store, staking.ValidatorsKey)
counter := int16(0)
Expand Down Expand Up @@ -161,6 +177,7 @@ func (app *BandApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList []st
/* Handle slashing state. */

// reset start height on signing infos
ctx.Logger().Info("Reset start height on signing infos")
app.SlashingKeeper.IterateValidatorSigningInfos(
ctx,
func(addr sdk.ConsAddress, info slashing.ValidatorSigningInfo) (stop bool) {
Expand Down
8 changes: 6 additions & 2 deletions chain/cmd/bandd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"encoding/json"
"io"
"os"
"path/filepath"
"strconv"
"strings"
Expand Down Expand Up @@ -140,9 +141,12 @@ func newApp(logger log.Logger, db dbm.DB, traceStore io.Writer) abci.Application
func exportAppStateAndTMValidators(
logger log.Logger, db dbm.DB, traceStore io.Writer, height int64, forZeroHeight bool, jailWhiteList []string,
) (json.RawMessage, []tmtypes.GenesisValidator, error) {
newLogger := log.NewTMLogger(log.NewSyncWriter(os.Stderr))
newLogger.Info("Start exporting genesis file...")

if height != -1 {
bandApp := app.NewBandApp(logger, db, traceStore, false, uint(1), map[int64]bool{}, "", viper.GetBool(flagDisableFeelessReports), viper.GetUint32(flagWithOwasmCacheSize))
bandApp := app.NewBandApp(newLogger, db, traceStore, false, uint(1), map[int64]bool{}, "", viper.GetBool(flagDisableFeelessReports), viper.GetUint32(flagWithOwasmCacheSize))
newLogger.Info("Setup store at specific height", "height", height)
err := bandApp.LoadHeight(height)
if err != nil {
return nil, nil, err
Expand All @@ -151,6 +155,6 @@ func exportAppStateAndTMValidators(
return bandApp.ExportAppStateAndValidators(forZeroHeight, jailWhiteList)
}

bandApp := app.NewBandApp(logger, db, traceStore, true, uint(1), map[int64]bool{}, "", viper.GetBool(flagDisableFeelessReports), viper.GetUint32(flagWithOwasmCacheSize))
bandApp := app.NewBandApp(newLogger, db, traceStore, true, uint(1), map[int64]bool{}, "", viper.GetBool(flagDisableFeelessReports), viper.GetUint32(flagWithOwasmCacheSize))
return bandApp.ExportAppStateAndValidators(forZeroHeight, jailWhiteList)
}
15 changes: 12 additions & 3 deletions chain/x/oracle/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ import (

// GenesisState is the oracle state that must be provided at genesis.
type GenesisState struct {
Params types.Params `json:"params" yaml:"params"`
DataSources []types.DataSource `json:"data_sources" yaml:"data_sources"`
OracleScripts []types.OracleScript `json:"oracle_scripts" yaml:"oracle_scripts"`
Params types.Params `json:"params" yaml:"params"`
DataSources []types.DataSource `json:"data_sources" yaml:"data_sources"`
OracleScripts []types.OracleScript `json:"oracle_scripts" yaml:"oracle_scripts"`
Reporters []types.ReportersPerValidator `json:"reporters" yaml:"reporters"`
}

// DefaultGenesisState returns the default oracle genesis state.
Expand All @@ -23,6 +24,7 @@ func DefaultGenesisState() GenesisState {
Params: types.DefaultParams(),
DataSources: []types.DataSource{},
OracleScripts: []types.OracleScript{},
Reporters: []types.ReportersPerValidator{},
}
}

Expand All @@ -47,6 +49,12 @@ func InitGenesis(ctx sdk.Context, k Keeper, data GenesisState) []abci.ValidatorU
for _, oracleScript := range data.OracleScripts {
_ = k.AddOracleScript(ctx, oracleScript)
}
for _, reportersPerValidator := range data.Reporters {
for _, reporter := range reportersPerValidator.Reporters {
k.AddReporter(ctx, reportersPerValidator.Validator, reporter)
}
}

return []abci.ValidatorUpdate{}
}

Expand All @@ -56,6 +64,7 @@ func ExportGenesis(ctx sdk.Context, k Keeper) GenesisState {
Params: k.GetParams(ctx),
DataSources: k.GetAllDataSources(ctx),
OracleScripts: k.GetAllOracleScripts(ctx),
Reporters: k.GetAllReporters(ctx),
}
}

Expand Down
13 changes: 13 additions & 0 deletions chain/x/oracle/keeper/reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/staking/exported"

"github.com/bandprotocol/bandchain/chain/x/oracle/types"
)
Expand Down Expand Up @@ -51,3 +52,15 @@ func (k Keeper) GetReporters(ctx sdk.Context, val sdk.ValAddress) (reporters []s
}
return reporters
}

func (k Keeper) GetAllReporters(ctx sdk.Context) []types.ReportersPerValidator {
var reporterList []types.ReportersPerValidator
k.stakingKeeper.IterateBondedValidatorsByPower(ctx, func(index int64, validator exported.ValidatorI) (stop bool) {
valAddress := validator.GetOperator()
reporters := k.GetReporters(ctx, valAddress)
reporterList = append(reporterList, types.NewReportersPerValidator(valAddress, reporters))
return false
})

return reporterList
}
44 changes: 44 additions & 0 deletions chain/x/oracle/keeper/reporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package keeper_test
import (
"testing"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"

"github.com/bandprotocol/bandchain/chain/x/oracle/testapp"
Expand Down Expand Up @@ -62,3 +63,46 @@ func TestGetReporters(t *testing.T) {
require.Contains(t, reporters, testapp.Bob.Address)
require.Contains(t, reporters, testapp.Carol.Address)
}

func TestGetAllReporters(t *testing.T) {
_, ctx, k := testapp.CreateTestInput(true)
// Initially, only validators should be reporters of themselves
reporters := k.GetAllReporters(ctx)
expectedReporterMap := map[string][]sdk.AccAddress{
sdk.ValAddress(testapp.Validator1.Address).String(): {testapp.Validator1.Address},
sdk.ValAddress(testapp.Validator2.Address).String(): {testapp.Validator2.Address},
sdk.ValAddress(testapp.Validator3.Address).String(): {testapp.Validator3.Address},
}
require.Equal(t, len(expectedReporterMap), len(reporters))
for _, reportersPerValidator := range reporters {
valAddr := sdk.ValAddress(reportersPerValidator.Validator).String()
require.Contains(t, expectedReporterMap, valAddr)
for _, reporter := range reportersPerValidator.Reporters {
require.Contains(t, expectedReporterMap[valAddr], reporter)
}
}

// After Alice, Bob, and Carol are added, they should be included in result of GetAllReporters
err := k.AddReporter(ctx, testapp.Validator1.ValAddress, testapp.Alice.Address)
require.NoError(t, err)
err = k.AddReporter(ctx, testapp.Validator1.ValAddress, testapp.Bob.Address)
require.NoError(t, err)
err = k.AddReporter(ctx, testapp.Validator3.ValAddress, testapp.Carol.Address)
require.NoError(t, err)

reporters = k.GetAllReporters(ctx)
expectedReporterMap = map[string][]sdk.AccAddress{
sdk.ValAddress(testapp.Validator1.Address).String(): {testapp.Validator1.Address, testapp.Bob.Address, testapp.Alice.Address},
sdk.ValAddress(testapp.Validator2.Address).String(): {testapp.Validator2.Address},
sdk.ValAddress(testapp.Validator3.Address).String(): {testapp.Validator3.Address, testapp.Carol.Address},
}

require.Equal(t, len(expectedReporterMap), len(reporters))
for _, reportersPerValidator := range reporters {
valAddr := sdk.ValAddress(reportersPerValidator.Validator).String()
require.Contains(t, expectedReporterMap, valAddr)
for _, reporter := range reportersPerValidator.Reporters {
require.Contains(t, expectedReporterMap[valAddr], reporter)
}
}
}
17 changes: 17 additions & 0 deletions chain/x/oracle/types/reporter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package types

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

// ReportersPerValidator represents list of reporter address and their associated validator
type ReportersPerValidator struct {
Validator sdk.ValAddress `json:"validator" yaml:"validator"`
Reporters []sdk.AccAddress `json:"reporters" yaml:"reporters"`
}

// NewReportersPerValidator creates new instance of ReportersPerValidator
func NewReportersPerValidator(validator sdk.ValAddress, reporters []sdk.AccAddress) ReportersPerValidator {
return ReportersPerValidator{
Validator: validator,
Reporters: reporters,
}
}

0 comments on commit bc58a72

Please sign in to comment.