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 [Staging PR 2/3] genesis generalization #4128

Closed
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
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
78 changes: 41 additions & 37 deletions cmd/gaia/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,22 +74,40 @@ type GaiaApp struct {
// custom tx codec
func MakeCodec() *codec.Codec {
var cdc = codec.New()
bank.RegisterCodec(cdc)
staking.RegisterCodec(cdc)
distr.RegisterCodec(cdc)
slashing.RegisterCodec(cdc)
gov.RegisterCodec(cdc)
auth.RegisterCodec(cdc)
crisis.RegisterCodec(cdc)
//bank.RegisterCodec(cdc)
//staking.RegisterCodec(cdc)
//distr.RegisterCodec(cdc)
//slashing.RegisterCodec(cdc)
//gov.RegisterCodec(cdc)
//auth.RegisterCodec(cdc)
//crisis.RegisterCodec(cdc)

for _, mb := range moduleBasics {
mb.RegisterCodec(cdc)
}
sdk.RegisterCodec(cdc)
codec.RegisterCrypto(cdc)
return cdc
}

var moduleBasics []sdk.AppModuleBasics

func init() {
moduleBasics := []sdk.AppModuleBasics{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ineffectual assignment to moduleBasics (from ineffassign)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to know that this thing actually works :)

bank.AppModuleBasics,
staking.AppModuleBasics,
distr.AppModuleBasics,
slashing.AppModuleBasics,
bank.AppModuleBasics,
gov.AppModuleBasics,
auth.AppModuleBasics,
crisis.AppModuleBasics,
}
}

// NewGaiaApp returns a reference to an initialized GaiaApp.
func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool,
invCheckPeriod uint,
baseAppOptions ...func(*bam.BaseApp)) *GaiaApp {
invCheckPeriod uint, baseAppOptions ...func(*bam.BaseApp)) *GaiaApp {

cdc := MakeCodec()

Expand Down Expand Up @@ -148,7 +166,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest b
staking.NewMultiStakingHooks(app.distrKeeper.Hooks(), app.slashingKeeper.Hooks()))

app.mm = sdk.NewModuleManager(
auth.NewAppModule(app.accountKeeper),
auth.NewAppModule(app.accountKeeper, app.feeCollectionKeeper),
bank.NewAppModule(app.bankKeeper, app.accountKeeper),
crisis.NewAppModule(app.crisisKeeper, app.Logger()),
distr.NewAppModule(app.distrKeeper),
Expand All @@ -164,7 +182,8 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest b
// TODO: slashing should really happen at EndBlocker.
app.mm.SetOrderBeginBlockers(mint.ModuleName, distr.ModuleName, slashing.ModuleName)
app.mm.SetOrderEndBlockers(gov.ModuleName, staking.ModuleName)
app.mm.SetOrderInitGenesis(crisis.ModuleName) // XXX this only is for invariant checks right now
app.mm.SetOrderInitGenesis(distr.ModuleName, staking.ModuleName, auth.ModuleName, bank.ModuleName,
slashing.ModuleName, gov.ModuleName, mint.ModuleName, crisis.ModuleName)
app.mm.RegisterInvariants(&app.crisisKeeper)
app.mm.RegisterRoutes(app.Router(), app.QueryRouter())

Expand Down Expand Up @@ -208,25 +227,11 @@ func (app *GaiaApp) initFromGenesisState(ctx sdk.Context, genesisState GenesisSt
app.accountKeeper.SetAccount(ctx, acc)
}

// initialize distribution (must happen before staking)
distr.InitGenesis(ctx, app.distrKeeper, genesisState.DistrData)

// load the initial staking information
validators, err := staking.InitGenesis(ctx, app.stakingKeeper, genesisState.StakingData)
if err != nil {
panic(err)
}

// initialize module-specific stores
auth.InitGenesis(ctx, app.accountKeeper, app.feeCollectionKeeper, genesisState.AuthData)
bank.InitGenesis(ctx, app.bankKeeper, genesisState.BankData)
slashing.InitGenesis(ctx, app.slashingKeeper, genesisState.SlashingData, genesisState.StakingData.Validators.ToSDKValidators())
gov.InitGenesis(ctx, app.govKeeper, genesisState.GovData)
mint.InitGenesis(ctx, app.mintKeeper, genesisState.MintData)
crisis.InitGenesis(ctx, app.crisisKeeper, genesisState.CrisisData)
// initialize modules
validators := app.mm.InitGenesis(ctx, genesisState.Modules)

// validate genesis state
if err := GaiaValidateGenesisState(genesisState); err != nil {
if err := app.GaiaValidateGenesisState(genesisState); err != nil {
panic(err)
}

Expand All @@ -237,6 +242,14 @@ func (app *GaiaApp) initFromGenesisState(ctx sdk.Context, genesisState GenesisSt
return validators
}

// GaiaValidateGenesisState ensures that the genesis state obeys the expected invariants
func (app *GaiaApp) GaiaValidateGenesisState(genesisState GenesisState) error {
if err := validateGenesisStateAccounts(genesisState.Accounts); err != nil {
return err
}
return app.mm.ValidateGenesis(genesisState.Modules)
}

type deliverTxFn func([]byte) abci.ResponseDeliverTx

// TODO move this genTx functionality to staking
Expand All @@ -260,15 +273,6 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci
app.cdc.MustUnmarshalJSON(req.AppStateBytes, &genesisState)
validators := app.initFromGenesisState(ctx, genesisState)

// XXX this is a temporary partial init-genesis implementation to allow for
// an invariance check for the crisis module
ctx = app.NewContext(false, abci.Header{Height: app.LastBlockHeight() + 1})
dummyGenesisData := make(map[string]json.RawMessage)
_, err := app.mm.InitGenesis(ctx, dummyGenesisData)
if err != nil {
panic(err)
}

return abci.ResponseInitChain{
Validators: validators,
}
Expand Down
14 changes: 1 addition & 13 deletions cmd/gaia/app/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/crisis"
distr "github.com/cosmos/cosmos-sdk/x/distribution"
"github.com/cosmos/cosmos-sdk/x/gov"
"github.com/cosmos/cosmos-sdk/x/mint"
"github.com/cosmos/cosmos-sdk/x/slashing"
"github.com/cosmos/cosmos-sdk/x/staking"
)
Expand All @@ -41,14 +36,7 @@ func (app *GaiaApp) ExportAppStateAndValidators(forZeroHeight bool, jailWhiteLis

genState := NewGenesisState(
accounts,
auth.ExportGenesis(ctx, app.accountKeeper, app.feeCollectionKeeper),
bank.ExportGenesis(ctx, app.bankKeeper),
staking.ExportGenesis(ctx, app.stakingKeeper),
mint.ExportGenesis(ctx, app.mintKeeper),
distr.ExportGenesis(ctx, app.distrKeeper),
gov.ExportGenesis(ctx, app.govKeeper),
crisis.ExportGenesis(ctx, app.crisisKeeper),
slashing.ExportGenesis(ctx, app.slashingKeeper),
app.mm.ExportGenesis(ctx),
)
appState, err = codec.MarshalJSONIndent(app.cdc, genState)
if err != nil {
Expand Down
204 changes: 23 additions & 181 deletions cmd/gaia/app/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,58 +4,30 @@ import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"sort"
"strings"
"time"

tmtypes "github.com/tendermint/tendermint/types"

"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/crisis"
distr "github.com/cosmos/cosmos-sdk/x/distribution"
"github.com/cosmos/cosmos-sdk/x/gov"
"github.com/cosmos/cosmos-sdk/x/mint"
"github.com/cosmos/cosmos-sdk/x/slashing"
"github.com/cosmos/cosmos-sdk/x/staking"
)

// XXX should use map for all module data

// State to Unmarshal
type GenesisState struct {
Accounts []GenesisAccount `json:"accounts"`
AuthData auth.GenesisState `json:"auth"`
BankData bank.GenesisState `json:"bank"`
StakingData staking.GenesisState `json:"staking"`
MintData mint.GenesisState `json:"mint"`
DistrData distr.GenesisState `json:"distr"`
GovData gov.GenesisState `json:"gov"`
CrisisData crisis.GenesisState `json:"crisis"`
SlashingData slashing.GenesisState `json:"slashing"`
GenTxs []json.RawMessage `json:"gentxs"`
Accounts []GenesisAccount `json:"accounts"`
Modules map[string]json.RawMessage `json:"modules"`
GenTxs []json.RawMessage `json:"gentxs"`
}

func NewGenesisState(accounts []GenesisAccount, authData auth.GenesisState,
bankData bank.GenesisState, stakingData staking.GenesisState, mintData mint.GenesisState,
distrData distr.GenesisState, govData gov.GenesisState, crisisData crisis.GenesisState,
slashingData slashing.GenesisState) GenesisState {

// NewGenesisState creates a new GenesisState object
func NewGenesisState(accounts []GenesisAccount, modules map[string]json.RawMessage, genTxs []json.RawMessage) GenesisState {
return GenesisState{
Accounts: accounts,
AuthData: authData,
BankData: bankData,
StakingData: stakingData,
MintData: mintData,
DistrData: distrData,
GovData: govData,
CrisisData: crisisData,
SlashingData: slashingData,
Accounts: accounts,
Modules: modules,
GenTxs: genTxs,
}
}

Expand Down Expand Up @@ -203,55 +175,25 @@ func GaiaAppGenStateJSON(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs

// NewDefaultGenesisState generates the default state for gaia.
func NewDefaultGenesisState() GenesisState {
return GenesisState{
Accounts: nil,
AuthData: auth.DefaultGenesisState(),
BankData: bank.DefaultGenesisState(),
StakingData: staking.DefaultGenesisState(),
MintData: mint.DefaultGenesisState(),
DistrData: distr.DefaultGenesisState(),
GovData: gov.DefaultGenesisState(),
CrisisData: crisis.DefaultGenesisState(),
SlashingData: slashing.DefaultGenesisState(),
GenTxs: nil,
}
}

// GaiaValidateGenesisState ensures that the genesis state obeys the expected invariants
// TODO: Ensure all state machine parameters are in genesis (#1704)
func GaiaValidateGenesisState(genesisState GenesisState) error {
if err := validateGenesisStateAccounts(genesisState.Accounts); err != nil {
return err
}

// skip stakingData validation as genesis is created from txs
if len(genesisState.GenTxs) > 0 {
return nil
moduleGS := make(map[string]json.RawMessage)
for _, mb := range moduleBasics {
moduleGS[mb.Name()] = mb.DefaultGenesisState(cdc)
}

if err := auth.ValidateGenesis(genesisState.AuthData); err != nil {
return err
}
if err := bank.ValidateGenesis(genesisState.BankData); err != nil {
return err
}
if err := staking.ValidateGenesis(genesisState.StakingData); err != nil {
return err
}
if err := mint.ValidateGenesis(genesisState.MintData); err != nil {
return err
}
if err := distr.ValidateGenesis(genesisState.DistrData); err != nil {
return err
}
if err := gov.ValidateGenesis(genesisState.GovData); err != nil {
return err
}
if err := crisis.ValidateGenesis(genesisState.CrisisData); err != nil {
return err
return GenesisState{
Accounts: nil,
Modules: moduleGS,
//AuthData: auth.DefaultGenesisState(),
//BankData: bank.DefaultGenesisState(),
//StakingData: staking.DefaultGenesisState(),
//MintData: mint.DefaultGenesisState(),
//DistrData: distr.DefaultGenesisState(),
//GovData: gov.DefaultGenesisState(),
//CrisisData: crisis.DefaultGenesisState(),
//SlashingData: slashing.DefaultGenesisState(),
GenTxs: nil,
}

return slashing.ValidateGenesis(genesisState.SlashingData)
}

// validateGenesisStateAccounts performs validation of genesis accounts. It
Expand Down Expand Up @@ -288,103 +230,3 @@ func validateGenesisStateAccounts(accs []GenesisAccount) error {

return nil
}

// CollectStdTxs processes and validates application's genesis StdTxs and returns
// the list of appGenTxs, and persistent peers required to generate genesis.json.
func CollectStdTxs(cdc *codec.Codec, moniker string, genTxsDir string, genDoc tmtypes.GenesisDoc) (
appGenTxs []auth.StdTx, persistentPeers string, err error) {

var fos []os.FileInfo
fos, err = ioutil.ReadDir(genTxsDir)
if err != nil {
return appGenTxs, persistentPeers, err
}

// prepare a map of all accounts in genesis state to then validate
// against the validators addresses
var appState GenesisState
if err := cdc.UnmarshalJSON(genDoc.AppState, &appState); err != nil {
return appGenTxs, persistentPeers, err
}

addrMap := make(map[string]GenesisAccount, len(appState.Accounts))
for i := 0; i < len(appState.Accounts); i++ {
acc := appState.Accounts[i]
addrMap[acc.Address.String()] = acc
}

// addresses and IPs (and port) validator server info
var addressesIPs []string

for _, fo := range fos {
filename := filepath.Join(genTxsDir, fo.Name())
if !fo.IsDir() && (filepath.Ext(filename) != ".json") {
continue
}

// get the genStdTx
var jsonRawTx []byte
if jsonRawTx, err = ioutil.ReadFile(filename); err != nil {
return appGenTxs, persistentPeers, err
}
var genStdTx auth.StdTx
if err = cdc.UnmarshalJSON(jsonRawTx, &genStdTx); err != nil {
return appGenTxs, persistentPeers, err
}
appGenTxs = append(appGenTxs, genStdTx)

// the memo flag is used to store
// the ip and node-id, for example this may be:
// "[email protected]:26656"
nodeAddrIP := genStdTx.GetMemo()
if len(nodeAddrIP) == 0 {
return appGenTxs, persistentPeers, fmt.Errorf(
"couldn't find node's address and IP in %s", fo.Name())
}

// genesis transactions must be single-message
msgs := genStdTx.GetMsgs()
if len(msgs) != 1 {

return appGenTxs, persistentPeers, errors.New(
"each genesis transaction must provide a single genesis message")
}

msg := msgs[0].(staking.MsgCreateValidator)
// validate delegator and validator addresses and funds against the accounts in the state
delAddr := msg.DelegatorAddress.String()
valAddr := sdk.AccAddress(msg.ValidatorAddress).String()

delAcc, delOk := addrMap[delAddr]
_, valOk := addrMap[valAddr]

accsNotInGenesis := []string{}
if !delOk {
accsNotInGenesis = append(accsNotInGenesis, delAddr)
}
if !valOk {
accsNotInGenesis = append(accsNotInGenesis, valAddr)
}
if len(accsNotInGenesis) != 0 {
return appGenTxs, persistentPeers, fmt.Errorf(
"account(s) %v not in genesis.json: %+v", strings.Join(accsNotInGenesis, " "), addrMap)
}

if delAcc.Coins.AmountOf(msg.Value.Denom).LT(msg.Value.Amount) {
return appGenTxs, persistentPeers, fmt.Errorf(
"insufficient fund for delegation %v: %v < %v",
delAcc.Address, delAcc.Coins.AmountOf(msg.Value.Denom), msg.Value.Amount,
)
}

// exclude itself from persistent peers
if msg.Description.Moniker != moniker {
addressesIPs = append(addressesIPs, nodeAddrIP)
}
}

sort.Strings(addressesIPs)
persistentPeers = strings.Join(addressesIPs, ",")

return appGenTxs, persistentPeers, nil
}
Loading