Merge pull request #901 from cosmos/cwgoes/dump-state-to-json
Dump all state to JSON
This commit is contained in:
commit
71dccd4db3
@ -241,6 +241,7 @@ func (app *BaseApp) setDeliverState(header abci.Header) {
|
||||
}
|
||||
|
||||
//______________________________________________________________________________
|
||||
|
||||
// ABCI
|
||||
|
||||
// Implements ABCI
|
||||
|
||||
@ -80,7 +80,7 @@ func createHandler(cdc *wire.Codec) http.Handler {
|
||||
keys.RegisterRoutes(r)
|
||||
rpc.RegisterRoutes(ctx, r)
|
||||
tx.RegisterRoutes(ctx, r, cdc)
|
||||
auth.RegisterRoutes(ctx, r, cdc, "main")
|
||||
auth.RegisterRoutes(ctx, r, cdc, "acc")
|
||||
bank.RegisterRoutes(ctx, r, cdc, kb)
|
||||
ibc.RegisterRoutes(ctx, r, cdc, kb)
|
||||
return r
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
@ -58,8 +59,14 @@ func NewGaiaApp(logger log.Logger, db dbm.DB) *GaiaApp {
|
||||
keyStake: sdk.NewKVStoreKey("stake"),
|
||||
}
|
||||
|
||||
// add accountMapper/handlers
|
||||
app.accountMapper = auth.NewAccountMapper(app.cdc, app.keyMain, &auth.BaseAccount{})
|
||||
// define the accountMapper
|
||||
app.accountMapper = auth.NewAccountMapper(
|
||||
app.cdc,
|
||||
app.keyAccount, // target store
|
||||
&auth.BaseAccount{}, // prototype
|
||||
)
|
||||
|
||||
// add handlers
|
||||
app.coinKeeper = bank.NewKeeper(app.accountMapper)
|
||||
app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace))
|
||||
app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.coinKeeper, app.RegisterCodespace(stake.DefaultCodespace))
|
||||
@ -117,3 +124,23 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci
|
||||
|
||||
return abci.ResponseInitChain{}
|
||||
}
|
||||
|
||||
// export the state of gaia for a genesis f
|
||||
func (app *GaiaApp) ExportAppStateJSON() (appState json.RawMessage, err error) {
|
||||
ctx := app.NewContext(true, abci.Header{})
|
||||
|
||||
// iterate to get the accounts
|
||||
accounts := []GenesisAccount{}
|
||||
appendAccount := func(acc sdk.Account) (stop bool) {
|
||||
account := NewGenesisAccountI(acc)
|
||||
accounts = append(accounts, account)
|
||||
return false
|
||||
}
|
||||
app.accountMapper.IterateAccounts(ctx, appendAccount)
|
||||
|
||||
genState := GenesisState{
|
||||
Accounts: accounts,
|
||||
StakeData: stake.WriteGenesis(ctx, app.stakeKeeper),
|
||||
}
|
||||
return wire.MarshalJSONIndent(app.cdc, genState)
|
||||
}
|
||||
|
||||
@ -35,6 +35,13 @@ func NewGenesisAccount(acc *auth.BaseAccount) GenesisAccount {
|
||||
}
|
||||
}
|
||||
|
||||
func NewGenesisAccountI(acc sdk.Account) GenesisAccount {
|
||||
return GenesisAccount{
|
||||
Address: acc.GetAddress(),
|
||||
Coins: acc.GetCoins(),
|
||||
}
|
||||
}
|
||||
|
||||
// convert GenesisAccount to auth.BaseAccount
|
||||
func (ga *GenesisAccount) ToAccount() (acc *auth.BaseAccount) {
|
||||
return &auth.BaseAccount{
|
||||
|
||||
@ -44,7 +44,7 @@ func main() {
|
||||
// add query/post commands (custom to binary)
|
||||
rootCmd.AddCommand(
|
||||
client.GetCommands(
|
||||
authcmd.GetAccountCmd("main", cdc, authcmd.GetAccountDecoder(cdc)),
|
||||
authcmd.GetAccountCmd("acc", cdc, authcmd.GetAccountDecoder(cdc)),
|
||||
stakecmd.GetCmdQueryCandidate("stake", cdc),
|
||||
//stakecmd.GetCmdQueryCandidates("stake", cdc),
|
||||
stakecmd.GetCmdQueryDelegatorBond("stake", cdc),
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
@ -23,19 +23,20 @@ func main() {
|
||||
PersistentPreRunE: server.PersistentPreRunEFn(ctx),
|
||||
}
|
||||
|
||||
server.AddCommands(ctx, cdc, rootCmd, app.GaiaAppInit(), generateApp)
|
||||
server.AddCommands(ctx, cdc, rootCmd, app.GaiaAppInit(),
|
||||
server.ConstructAppCreator(newApp, "gaia"),
|
||||
server.ConstructAppExporter(exportAppState, "gaia"))
|
||||
|
||||
// prepare and add flags
|
||||
executor := cli.PrepareBaseCmd(rootCmd, "GA", app.DefaultNodeHome)
|
||||
executor.Execute()
|
||||
}
|
||||
|
||||
func generateApp(rootDir string, logger log.Logger) (abci.Application, error) {
|
||||
dataDir := filepath.Join(rootDir, "data")
|
||||
db, err := dbm.NewGoLevelDB("gaia", dataDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bapp := app.NewGaiaApp(logger, db)
|
||||
return bapp, nil
|
||||
func newApp(logger log.Logger, db dbm.DB) abci.Application {
|
||||
return app.NewGaiaApp(logger, db)
|
||||
}
|
||||
|
||||
func exportAppState(logger log.Logger, db dbm.DB) (json.RawMessage, error) {
|
||||
gapp := app.NewGaiaApp(logger, db)
|
||||
return gapp.ExportAppStateJSON()
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
dbm "github.com/tendermint/tmlibs/db"
|
||||
@ -57,7 +59,7 @@ func NewBasecoinApp(logger log.Logger, db dbm.DB) *BasecoinApp {
|
||||
// Define the accountMapper.
|
||||
app.accountMapper = auth.NewAccountMapper(
|
||||
cdc,
|
||||
app.keyMain, // target store
|
||||
app.keyAccount, // target store
|
||||
&types.AppAccount{}, // prototype
|
||||
)
|
||||
|
||||
@ -119,3 +121,25 @@ func (app *BasecoinApp) initChainer(ctx sdk.Context, req abci.RequestInitChain)
|
||||
}
|
||||
return abci.ResponseInitChain{}
|
||||
}
|
||||
|
||||
// Custom logic for state export
|
||||
func (app *BasecoinApp) ExportAppStateJSON() (appState json.RawMessage, err error) {
|
||||
ctx := app.NewContext(true, abci.Header{})
|
||||
|
||||
// iterate to get the accounts
|
||||
accounts := []*types.GenesisAccount{}
|
||||
appendAccount := func(acc sdk.Account) (stop bool) {
|
||||
account := &types.GenesisAccount{
|
||||
Address: acc.GetAddress(),
|
||||
Coins: acc.GetCoins(),
|
||||
}
|
||||
accounts = append(accounts, account)
|
||||
return false
|
||||
}
|
||||
app.accountMapper.IterateAccounts(ctx, appendAccount)
|
||||
|
||||
genState := types.GenesisState{
|
||||
Accounts: accounts,
|
||||
}
|
||||
return wire.MarshalJSONIndent(app.cdc, genState)
|
||||
}
|
||||
|
||||
@ -14,11 +14,13 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/version"
|
||||
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
|
||||
bankcmd "github.com/cosmos/cosmos-sdk/x/bank/client/cli"
|
||||
ibccmd "github.com/cosmos/cosmos-sdk/x/ibc/client/cli"
|
||||
stakecmd "github.com/cosmos/cosmos-sdk/x/stake/client/cli"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/examples/basecoin/app"
|
||||
"github.com/cosmos/cosmos-sdk/examples/basecoin/types"
|
||||
)
|
||||
|
||||
// rootCmd is the entry point for this binary
|
||||
@ -47,6 +49,11 @@ func main() {
|
||||
rootCmd.AddCommand(client.LineBreak)
|
||||
|
||||
// add query/post commands (custom to binary)
|
||||
rootCmd.AddCommand(
|
||||
client.GetCommands(
|
||||
authcmd.GetAccountCmd("acc", cdc, types.GetAccountDecoder(cdc)),
|
||||
)...)
|
||||
|
||||
rootCmd.AddCommand(
|
||||
client.PostCommands(
|
||||
bankcmd.SendTxCmd(cdc),
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
@ -25,7 +25,9 @@ func main() {
|
||||
PersistentPreRunE: server.PersistentPreRunEFn(ctx),
|
||||
}
|
||||
|
||||
server.AddCommands(ctx, cdc, rootCmd, server.DefaultAppInit, generateApp)
|
||||
server.AddCommands(ctx, cdc, rootCmd, server.DefaultAppInit,
|
||||
server.ConstructAppCreator(newApp, "basecoin"),
|
||||
server.ConstructAppExporter(exportAppState, "basecoin"))
|
||||
|
||||
// prepare and add flags
|
||||
rootDir := os.ExpandEnv("$HOME/.basecoind")
|
||||
@ -33,12 +35,11 @@ func main() {
|
||||
executor.Execute()
|
||||
}
|
||||
|
||||
func generateApp(rootDir string, logger log.Logger) (abci.Application, error) {
|
||||
dataDir := filepath.Join(rootDir, "data")
|
||||
db, err := dbm.NewGoLevelDB("basecoin", dataDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bapp := app.NewBasecoinApp(logger, db)
|
||||
return bapp, nil
|
||||
func newApp(logger log.Logger, db dbm.DB) abci.Application {
|
||||
return app.NewBasecoinApp(logger, db)
|
||||
}
|
||||
|
||||
func exportAppState(logger log.Logger, db dbm.DB) (json.RawMessage, error) {
|
||||
bapp := app.NewBasecoinApp(logger, db)
|
||||
return bapp.ExportAppStateJSON()
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
dbm "github.com/tendermint/tmlibs/db"
|
||||
@ -36,6 +38,13 @@ type DemocoinApp struct {
|
||||
capKeyIBCStore *sdk.KVStoreKey
|
||||
capKeyStakingStore *sdk.KVStoreKey
|
||||
|
||||
// keepers
|
||||
coinKeeper bank.Keeper
|
||||
coolKeeper cool.Keeper
|
||||
powKeeper pow.Keeper
|
||||
ibcMapper ibc.Mapper
|
||||
stakeKeeper simplestake.Keeper
|
||||
|
||||
// Manage getting and setting accounts
|
||||
accountMapper sdk.AccountMapper
|
||||
}
|
||||
@ -59,26 +68,26 @@ func NewDemocoinApp(logger log.Logger, db dbm.DB) *DemocoinApp {
|
||||
// Define the accountMapper.
|
||||
app.accountMapper = auth.NewAccountMapper(
|
||||
cdc,
|
||||
app.capKeyMainStore, // target store
|
||||
&types.AppAccount{}, // prototype
|
||||
app.capKeyAccountStore, // target store
|
||||
&types.AppAccount{}, // prototype
|
||||
)
|
||||
|
||||
// Add handlers.
|
||||
coinKeeper := bank.NewKeeper(app.accountMapper)
|
||||
coolKeeper := cool.NewKeeper(app.capKeyMainStore, coinKeeper, app.RegisterCodespace(cool.DefaultCodespace))
|
||||
powKeeper := pow.NewKeeper(app.capKeyPowStore, pow.NewConfig("pow", int64(1)), coinKeeper, app.RegisterCodespace(pow.DefaultCodespace))
|
||||
ibcMapper := ibc.NewMapper(app.cdc, app.capKeyIBCStore, app.RegisterCodespace(ibc.DefaultCodespace))
|
||||
stakeKeeper := simplestake.NewKeeper(app.capKeyStakingStore, coinKeeper, app.RegisterCodespace(simplestake.DefaultCodespace))
|
||||
app.coinKeeper = bank.NewKeeper(app.accountMapper)
|
||||
app.coolKeeper = cool.NewKeeper(app.capKeyMainStore, app.coinKeeper, app.RegisterCodespace(cool.DefaultCodespace))
|
||||
app.powKeeper = pow.NewKeeper(app.capKeyPowStore, pow.NewConfig("pow", int64(1)), app.coinKeeper, app.RegisterCodespace(pow.DefaultCodespace))
|
||||
app.ibcMapper = ibc.NewMapper(app.cdc, app.capKeyIBCStore, app.RegisterCodespace(ibc.DefaultCodespace))
|
||||
app.stakeKeeper = simplestake.NewKeeper(app.capKeyStakingStore, app.coinKeeper, app.RegisterCodespace(simplestake.DefaultCodespace))
|
||||
app.Router().
|
||||
AddRoute("bank", bank.NewHandler(coinKeeper)).
|
||||
AddRoute("cool", cool.NewHandler(coolKeeper)).
|
||||
AddRoute("pow", powKeeper.Handler).
|
||||
AddRoute("bank", bank.NewHandler(app.coinKeeper)).
|
||||
AddRoute("cool", cool.NewHandler(app.coolKeeper)).
|
||||
AddRoute("pow", app.powKeeper.Handler).
|
||||
AddRoute("sketchy", sketchy.NewHandler()).
|
||||
AddRoute("ibc", ibc.NewHandler(ibcMapper, coinKeeper)).
|
||||
AddRoute("simplestake", simplestake.NewHandler(stakeKeeper))
|
||||
AddRoute("ibc", ibc.NewHandler(app.ibcMapper, app.coinKeeper)).
|
||||
AddRoute("simplestake", simplestake.NewHandler(app.stakeKeeper))
|
||||
|
||||
// Initialize BaseApp.
|
||||
app.SetInitChainer(app.initChainerFn(coolKeeper, powKeeper))
|
||||
app.SetInitChainer(app.initChainerFn(app.coolKeeper, app.powKeeper))
|
||||
app.MountStoresIAVL(app.capKeyMainStore, app.capKeyAccountStore, app.capKeyPowStore, app.capKeyIBCStore, app.capKeyStakingStore)
|
||||
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, auth.BurnFeeHandler))
|
||||
err := app.LoadLatestVersion(app.capKeyMainStore)
|
||||
@ -127,13 +136,13 @@ func (app *DemocoinApp) initChainerFn(coolKeeper cool.Keeper, powKeeper pow.Keep
|
||||
}
|
||||
|
||||
// Application specific genesis handling
|
||||
err = coolKeeper.InitGenesis(ctx, genesisState.CoolGenesis)
|
||||
err = cool.InitGenesis(ctx, app.coolKeeper, genesisState.CoolGenesis)
|
||||
if err != nil {
|
||||
panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468
|
||||
// return sdk.ErrGenesisParse("").TraceCause(err, "")
|
||||
}
|
||||
|
||||
err = powKeeper.InitGenesis(ctx, genesisState.POWGenesis)
|
||||
err = pow.InitGenesis(ctx, app.powKeeper, genesisState.POWGenesis)
|
||||
if err != nil {
|
||||
panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468
|
||||
// return sdk.ErrGenesisParse("").TraceCause(err, "")
|
||||
@ -142,3 +151,27 @@ func (app *DemocoinApp) initChainerFn(coolKeeper cool.Keeper, powKeeper pow.Keep
|
||||
return abci.ResponseInitChain{}
|
||||
}
|
||||
}
|
||||
|
||||
// Custom logic for state export
|
||||
func (app *DemocoinApp) ExportAppStateJSON() (appState json.RawMessage, err error) {
|
||||
ctx := app.NewContext(true, abci.Header{})
|
||||
|
||||
// iterate to get the accounts
|
||||
accounts := []*types.GenesisAccount{}
|
||||
appendAccount := func(acc sdk.Account) (stop bool) {
|
||||
account := &types.GenesisAccount{
|
||||
Address: acc.GetAddress(),
|
||||
Coins: acc.GetCoins(),
|
||||
}
|
||||
accounts = append(accounts, account)
|
||||
return false
|
||||
}
|
||||
app.accountMapper.IterateAccounts(ctx, appendAccount)
|
||||
|
||||
genState := types.GenesisState{
|
||||
Accounts: accounts,
|
||||
POWGenesis: pow.WriteGenesis(ctx, app.powKeeper),
|
||||
CoolGenesis: cool.WriteGenesis(ctx, app.coolKeeper),
|
||||
}
|
||||
return wire.MarshalJSONIndent(app.cdc, genState)
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ func main() {
|
||||
// start with commands common to basecoin
|
||||
rootCmd.AddCommand(
|
||||
client.GetCommands(
|
||||
authcmd.GetAccountCmd("main", cdc, types.GetAccountDecoder(cdc)),
|
||||
authcmd.GetAccountCmd("acc", cdc, types.GetAccountDecoder(cdc)),
|
||||
)...)
|
||||
rootCmd.AddCommand(
|
||||
client.PostCommands(
|
||||
|
||||
@ -3,7 +3,6 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
@ -32,18 +31,24 @@ func CoolAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (appState jso
|
||||
key := "cool"
|
||||
value := json.RawMessage(`{
|
||||
"trend": "ice-cold"
|
||||
}`)
|
||||
appState, err = server.AppendJSON(cdc, appState, key, value)
|
||||
key = "pow"
|
||||
value = json.RawMessage(`{
|
||||
"difficulty": 1,
|
||||
"count": 0
|
||||
}`)
|
||||
appState, err = server.AppendJSON(cdc, appState, key, value)
|
||||
return
|
||||
}
|
||||
|
||||
func generateApp(rootDir string, logger log.Logger) (abci.Application, error) {
|
||||
db, err := dbm.NewGoLevelDB("democoin", filepath.Join(rootDir, "data"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bapp := app.NewDemocoinApp(logger, db)
|
||||
return bapp, nil
|
||||
func newApp(logger log.Logger, db dbm.DB) abci.Application {
|
||||
return app.NewDemocoinApp(logger, db)
|
||||
}
|
||||
|
||||
func exportAppState(logger log.Logger, db dbm.DB) (json.RawMessage, error) {
|
||||
dapp := app.NewDemocoinApp(logger, db)
|
||||
return dapp.ExportAppStateJSON()
|
||||
}
|
||||
|
||||
func main() {
|
||||
@ -56,7 +61,9 @@ func main() {
|
||||
PersistentPreRunE: server.PersistentPreRunEFn(ctx),
|
||||
}
|
||||
|
||||
server.AddCommands(ctx, cdc, rootCmd, CoolAppInit, generateApp)
|
||||
server.AddCommands(ctx, cdc, rootCmd, CoolAppInit,
|
||||
server.ConstructAppCreator(newApp, "democoin"),
|
||||
server.ConstructAppExporter(exportAppState, "democoin"))
|
||||
|
||||
// prepare and add flags
|
||||
rootDir := os.ExpandEnv("$HOME/.democoind")
|
||||
|
||||
@ -44,7 +44,13 @@ func (k Keeper) CheckTrend(ctx sdk.Context, guessedTrend string) bool {
|
||||
}
|
||||
|
||||
// InitGenesis - store the genesis trend
|
||||
func (k Keeper) InitGenesis(ctx sdk.Context, data Genesis) error {
|
||||
func InitGenesis(ctx sdk.Context, k Keeper, data Genesis) error {
|
||||
k.setTrend(ctx, data.Trend)
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteGenesis - output the genesis trend
|
||||
func WriteGenesis(ctx sdk.Context, k Keeper) Genesis {
|
||||
trend := k.GetTrend(ctx)
|
||||
return Genesis{trend}
|
||||
}
|
||||
|
||||
50
examples/democoin/x/cool/keeper_test.go
Normal file
50
examples/democoin/x/cool/keeper_test.go
Normal file
@ -0,0 +1,50 @@
|
||||
package cool
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
dbm "github.com/tendermint/tmlibs/db"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/store"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/wire"
|
||||
auth "github.com/cosmos/cosmos-sdk/x/auth"
|
||||
bank "github.com/cosmos/cosmos-sdk/x/bank"
|
||||
)
|
||||
|
||||
func setupMultiStore() (sdk.MultiStore, *sdk.KVStoreKey) {
|
||||
db := dbm.NewMemDB()
|
||||
capKey := sdk.NewKVStoreKey("capkey")
|
||||
ms := store.NewCommitMultiStore(db)
|
||||
ms.MountStoreWithDB(capKey, sdk.StoreTypeIAVL, db)
|
||||
ms.LoadLatestVersion()
|
||||
return ms, capKey
|
||||
}
|
||||
|
||||
func TestCoolKeeper(t *testing.T) {
|
||||
ms, capKey := setupMultiStore()
|
||||
cdc := wire.NewCodec()
|
||||
auth.RegisterBaseAccount(cdc)
|
||||
|
||||
am := auth.NewAccountMapper(cdc, capKey, &auth.BaseAccount{})
|
||||
ctx := sdk.NewContext(ms, abci.Header{}, false, nil)
|
||||
ck := bank.NewKeeper(am)
|
||||
keeper := NewKeeper(capKey, ck, DefaultCodespace)
|
||||
|
||||
err := InitGenesis(ctx, keeper, Genesis{"icy"})
|
||||
assert.Nil(t, err)
|
||||
|
||||
genesis := WriteGenesis(ctx, keeper)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, genesis, Genesis{"icy"})
|
||||
|
||||
res := keeper.GetTrend(ctx)
|
||||
assert.Equal(t, res, "icy")
|
||||
|
||||
keeper.setTrend(ctx, "fiery")
|
||||
res = keeper.GetTrend(ctx)
|
||||
assert.Equal(t, res, "fiery")
|
||||
}
|
||||
@ -30,7 +30,7 @@ func TestPowHandler(t *testing.T) {
|
||||
count := uint64(1)
|
||||
difficulty := uint64(2)
|
||||
|
||||
err := keeper.InitGenesis(ctx, Genesis{uint64(1), uint64(0)})
|
||||
err := InitGenesis(ctx, keeper, Genesis{uint64(1), uint64(0)})
|
||||
assert.Nil(t, err)
|
||||
|
||||
nonce, proof := mine(addr, count, difficulty)
|
||||
|
||||
@ -36,13 +36,29 @@ func NewKeeper(key sdk.StoreKey, config Config, ck bank.Keeper, codespace sdk.Co
|
||||
return Keeper{key, config, ck, codespace}
|
||||
}
|
||||
|
||||
// Init Genessis for the POW module
|
||||
func (k Keeper) InitGenesis(ctx sdk.Context, genesis Genesis) error {
|
||||
// InitGenesis for the POW module
|
||||
func InitGenesis(ctx sdk.Context, k Keeper, genesis Genesis) error {
|
||||
k.SetLastDifficulty(ctx, genesis.Difficulty)
|
||||
k.SetLastCount(ctx, genesis.Count)
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteGenesis for the PoW module
|
||||
func WriteGenesis(ctx sdk.Context, k Keeper) Genesis {
|
||||
difficulty, err := k.GetLastDifficulty(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
count, err := k.GetLastCount(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return Genesis{
|
||||
difficulty,
|
||||
count,
|
||||
}
|
||||
}
|
||||
|
||||
var lastDifficultyKey = []byte("lastDifficultyKey")
|
||||
|
||||
// get the last mining difficulty
|
||||
|
||||
@ -37,9 +37,13 @@ func TestPowKeeperGetSet(t *testing.T) {
|
||||
ck := bank.NewKeeper(am)
|
||||
keeper := NewKeeper(capKey, config, ck, DefaultCodespace)
|
||||
|
||||
err := keeper.InitGenesis(ctx, Genesis{uint64(1), uint64(0)})
|
||||
err := InitGenesis(ctx, keeper, Genesis{uint64(1), uint64(0)})
|
||||
assert.Nil(t, err)
|
||||
|
||||
genesis := WriteGenesis(ctx, keeper)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, genesis, Genesis{uint64(1), uint64(0)})
|
||||
|
||||
res, err := keeper.GetLastDifficulty(ctx)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, res, uint64(1))
|
||||
|
||||
42
server/constructors.go
Normal file
42
server/constructors.go
Normal file
@ -0,0 +1,42 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"path/filepath"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
dbm "github.com/tendermint/tmlibs/db"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
)
|
||||
|
||||
// AppCreator lets us lazily initialize app, using home dir
|
||||
// and other flags (?) to start
|
||||
type AppCreator func(string, log.Logger) (abci.Application, error)
|
||||
|
||||
// AppExporter dumps all app state to JSON-serializable structure
|
||||
type AppExporter func(home string, log log.Logger) (json.RawMessage, error)
|
||||
|
||||
// ConstructAppCreator returns an application generation function
|
||||
func ConstructAppCreator(appFn func(log.Logger, dbm.DB) abci.Application, name string) AppCreator {
|
||||
return func(rootDir string, logger log.Logger) (abci.Application, error) {
|
||||
dataDir := filepath.Join(rootDir, "data")
|
||||
db, err := dbm.NewGoLevelDB(name, dataDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
app := appFn(logger, db)
|
||||
return app, nil
|
||||
}
|
||||
}
|
||||
|
||||
// ConstructAppExporter returns an application export function
|
||||
func ConstructAppExporter(appFn func(log.Logger, dbm.DB) (json.RawMessage, error), name string) AppExporter {
|
||||
return func(rootDir string, logger log.Logger) (json.RawMessage, error) {
|
||||
dataDir := filepath.Join(rootDir, "data")
|
||||
db, err := dbm.NewGoLevelDB(name, dataDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return appFn(logger, db)
|
||||
}
|
||||
}
|
||||
28
server/export.go
Normal file
28
server/export.go
Normal file
@ -0,0 +1,28 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/wire"
|
||||
)
|
||||
|
||||
// ExportCmd dumps app state to JSON
|
||||
func ExportCmd(ctx *Context, cdc *wire.Codec, appExporter AppExporter) *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "export",
|
||||
Short: "Export state to JSON",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
home := viper.GetString("home")
|
||||
appState, err := appExporter(home, ctx.Logger)
|
||||
if err != nil {
|
||||
return errors.Errorf("Error exporting state: %v\n", err)
|
||||
}
|
||||
fmt.Println(string(appState))
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -6,14 +6,12 @@ import (
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/tendermint/abci/server"
|
||||
abci "github.com/tendermint/abci/types"
|
||||
|
||||
tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
|
||||
"github.com/tendermint/tendermint/node"
|
||||
"github.com/tendermint/tendermint/proxy"
|
||||
pvm "github.com/tendermint/tendermint/types/priv_validator"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -21,10 +19,6 @@ const (
|
||||
flagAddress = "address"
|
||||
)
|
||||
|
||||
// AppCreator lets us lazily initialize app, using home dir
|
||||
// and other flags (?) to start
|
||||
type AppCreator func(string, log.Logger) (abci.Application, error)
|
||||
|
||||
// StartCmd runs the service passed in, either
|
||||
// stand-alone, or in-process with tendermint
|
||||
func StartCmd(ctx *Context, appCreator AppCreator) *cobra.Command {
|
||||
|
||||
@ -68,7 +68,7 @@ func PersistentPreRunEFn(context *Context) func(*cobra.Command, []string) error
|
||||
func AddCommands(
|
||||
ctx *Context, cdc *wire.Codec,
|
||||
rootCmd *cobra.Command, appInit AppInit,
|
||||
appCreator AppCreator) {
|
||||
appCreator AppCreator, appExport AppExporter) {
|
||||
|
||||
rootCmd.PersistentFlags().String("log_level", ctx.Config.LogLevel, "Log level")
|
||||
|
||||
@ -78,6 +78,8 @@ func AddCommands(
|
||||
UnsafeResetAllCmd(ctx),
|
||||
ShowNodeIDCmd(ctx),
|
||||
ShowValidatorCmd(ctx),
|
||||
ExportCmd(ctx, cdc, appExport),
|
||||
UnsafeResetAllCmd(ctx),
|
||||
version.VersionCmd,
|
||||
)
|
||||
}
|
||||
|
||||
@ -48,6 +48,7 @@ type AccountMapper interface {
|
||||
NewAccountWithAddress(ctx Context, addr Address) Account
|
||||
GetAccount(ctx Context, addr Address) Account
|
||||
SetAccount(ctx Context, acc Account)
|
||||
IterateAccounts(ctx Context, process func(Account) (stop bool))
|
||||
}
|
||||
|
||||
// AccountDecoder unmarshals account bytes
|
||||
|
||||
@ -1,10 +0,0 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
// Run only once on chain initialization, should write genesis state to store
|
||||
// or throw an error if some required information was not provided, in which case
|
||||
// the application will panic.
|
||||
type InitGenesis func(ctx Context, data json.RawMessage) error
|
||||
@ -62,6 +62,23 @@ func (am accountMapper) SetAccount(ctx sdk.Context, acc sdk.Account) {
|
||||
store.Set(addr, bz)
|
||||
}
|
||||
|
||||
// Implements sdk.AccountMapper.
|
||||
func (am accountMapper) IterateAccounts(ctx sdk.Context, process func(sdk.Account) (stop bool)) {
|
||||
store := ctx.KVStore(am.key)
|
||||
iter := store.Iterator(nil, nil)
|
||||
for {
|
||||
if !iter.Valid() {
|
||||
return
|
||||
}
|
||||
val := iter.Value()
|
||||
acc := am.decodeAccount(val)
|
||||
if process(acc) {
|
||||
return
|
||||
}
|
||||
iter.Next()
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
// misc.
|
||||
|
||||
|
||||
@ -55,6 +55,23 @@ func InitGenesis(ctx sdk.Context, k Keeper, data GenesisState) {
|
||||
for _, candidate := range data.Candidates {
|
||||
k.setCandidate(ctx, candidate)
|
||||
}
|
||||
for _, bond := range data.Bonds {
|
||||
k.setDelegatorBond(ctx, bond)
|
||||
}
|
||||
}
|
||||
|
||||
// WriteGenesis - output genesis parameters
|
||||
func WriteGenesis(ctx sdk.Context, k Keeper) GenesisState {
|
||||
pool := k.GetPool(ctx)
|
||||
params := k.GetParams(ctx)
|
||||
candidates := k.GetCandidates(ctx, 32767)
|
||||
bonds := k.getBonds(ctx, 32767)
|
||||
return GenesisState{
|
||||
pool,
|
||||
params,
|
||||
candidates,
|
||||
bonds,
|
||||
}
|
||||
}
|
||||
|
||||
//_____________________________________________________________________
|
||||
|
||||
@ -371,6 +371,30 @@ func (k Keeper) GetDelegatorBond(ctx sdk.Context,
|
||||
return bond, true
|
||||
}
|
||||
|
||||
// load all bonds
|
||||
func (k Keeper) getBonds(ctx sdk.Context, maxRetrieve int16) (bonds []DelegatorBond) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
iterator := store.Iterator(subspace(DelegatorBondKeyPrefix))
|
||||
|
||||
bonds = make([]DelegatorBond, maxRetrieve)
|
||||
i := 0
|
||||
for ; ; i++ {
|
||||
if !iterator.Valid() || i > int(maxRetrieve-1) {
|
||||
iterator.Close()
|
||||
break
|
||||
}
|
||||
bondBytes := iterator.Value()
|
||||
var bond DelegatorBond
|
||||
err := k.cdc.UnmarshalBinary(bondBytes, &bond)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
bonds[i] = bond
|
||||
iterator.Next()
|
||||
}
|
||||
return bonds[:i] // trim
|
||||
}
|
||||
|
||||
// load all bonds of a delegator
|
||||
func (k Keeper) GetDelegatorBonds(ctx sdk.Context, delegator sdk.Address, maxRetrieve int16) (bonds []DelegatorBond) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
|
||||
@ -94,7 +94,7 @@ func TestCandidate(t *testing.T) {
|
||||
assert.False(t, found)
|
||||
}
|
||||
|
||||
// tests GetDelegatorBond, GetDelegatorBonds, SetDelegatorBond, removeDelegatorBond
|
||||
// tests GetDelegatorBond, GetDelegatorBonds, SetDelegatorBond, removeDelegatorBond, GetBonds
|
||||
func TestBond(t *testing.T) {
|
||||
ctx, _, keeper := createTestInput(t, false, 0)
|
||||
|
||||
@ -172,6 +172,14 @@ func TestBond(t *testing.T) {
|
||||
assert.True(t, bondsEqual(bond2to1, resBonds[0]))
|
||||
assert.True(t, bondsEqual(bond2to2, resBonds[1]))
|
||||
assert.True(t, bondsEqual(bond2to3, resBonds[2]))
|
||||
allBonds := keeper.getBonds(ctx, 1000)
|
||||
require.Equal(t, 6, len(allBonds))
|
||||
assert.True(t, bondsEqual(bond1to1, allBonds[0]))
|
||||
assert.True(t, bondsEqual(bond1to2, allBonds[1]))
|
||||
assert.True(t, bondsEqual(bond1to3, allBonds[2]))
|
||||
assert.True(t, bondsEqual(bond2to1, allBonds[3]))
|
||||
assert.True(t, bondsEqual(bond2to2, allBonds[4]))
|
||||
assert.True(t, bondsEqual(bond2to3, allBonds[5]))
|
||||
|
||||
// delete a record
|
||||
keeper.removeDelegatorBond(ctx, bond2to3)
|
||||
|
||||
@ -9,9 +9,10 @@ import (
|
||||
|
||||
// GenesisState - all staking state that must be provided at genesis
|
||||
type GenesisState struct {
|
||||
Pool Pool `json:"pool"`
|
||||
Params Params `json:"params"`
|
||||
Candidates []Candidate `json:"candidates"`
|
||||
Pool Pool `json:"pool"`
|
||||
Params Params `json:"params"`
|
||||
Candidates []Candidate `json:"candidates"`
|
||||
Bonds []DelegatorBond `json:"bonds"`
|
||||
}
|
||||
|
||||
//_________________________________________________________________________
|
||||
|
||||
Loading…
Reference in New Issue
Block a user