From df0f3a22da2c865cd7aeefbfa237081490934a13 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 16 Oct 2017 17:34:29 +0200 Subject: [PATCH] Separate genesis parsing from basecoin --- app/app.go | 13 +---- app/app_test.go | 33 ++++++------ app/bc.go | 35 +++++++++---- app/genesis.go | 52 +++++++++++++++---- benchmarks/app_test.go | 8 +-- .../counter/plugins/counter/counter_test.go | 7 +-- 6 files changed, 93 insertions(+), 55 deletions(-) diff --git a/app/app.go b/app/app.go index 47fb34f311..fcac9cb9fe 100644 --- a/app/app.go +++ b/app/app.go @@ -20,8 +20,7 @@ import ( //nolint const ( - ModuleNameBase = "base" - ChainKey = "chain_id" + ChainKey = "chain_id" ) // BaseApp contains a data store and all info needed @@ -207,16 +206,6 @@ func pubKeyIndex(val *abci.Validator, list []*abci.Validator) int { return -1 } -// Splits the string at the first '/'. -// if there are none, assign default module ("base"). -func splitKey(key string) (string, string) { - if strings.Contains(key, "/") { - keyParts := strings.SplitN(key, "/", 2) - return keyParts[0], keyParts[1] - } - return ModuleNameBase, key -} - func loadState(dbName string, cacheSize int) (*sm.State, error) { // memory backed case, just for testing if dbName == "" { diff --git a/app/app_test.go b/app/app_test.go index bcf32dfbeb..5be1320daf 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -100,8 +100,8 @@ func (at *appTest) feeTx(coins coin.Coins, toll coin.Coin, sequence uint32) sdk. // set the account on the app through InitState func (at *appTest) initAccount(acct *coin.AccountWithKey) { - res := at.app.InitState("coin/account", acct.MakeOption()) - require.EqualValues(at.t, res, "Success") + _, err := at.app.InitState("coin", "account", acct.MakeOption()) + require.Nil(at.t, err, "%+v", err) } // reset the in and out accs to be one account each with 7mycoin @@ -122,8 +122,8 @@ func (at *appTest) reset() { ) require.Nil(at.t, err, "%+v", err) - res := at.app.InitState("base/chain_id", at.chainID) - require.EqualValues(at.t, res, "Success") + _, err = at.app.InitState("base", "chain_id", at.chainID) + require.Nil(at.t, err, "%+v", err) at.initAccount(at.acctIn) at.initAccount(at.acctOut) @@ -183,15 +183,15 @@ func TestInitState(t *testing.T) { //testing ChainID chainID := "testChain" - res := app.InitState("base/chain_id", chainID) + _, err = app.InitState("base", "chain_id", chainID) + require.Nil(err, "%+v", err) assert.EqualValues(app.GetChainID(), chainID) - assert.EqualValues(res, "Success") // make a nice account... bal := coin.Coins{{"atom", 77}, {"eth", 12}} acct := coin.NewAccountWithKey(bal) - res = app.InitState("coin/account", acct.MakeOption()) - require.EqualValues(res, "Success") + _, err = app.InitState("coin", "account", acct.MakeOption()) + require.Nil(err, "%+v", err) // make sure it is set correctly, with some balance coins, err := getBalance(acct.Actor(), app.Append()) @@ -218,23 +218,22 @@ func TestInitState(t *testing.T) { } ] }` - res = app.InitState("coin/account", unsortAcc) - require.EqualValues(res, "Success") + _, err = app.InitState("coin", "account", unsortAcc) + require.Nil(err, "%+v", err) coins, err = getAddr(unsortAddr, app.Append()) require.Nil(err) assert.True(coins.IsValid()) assert.Equal(unsortCoins, coins) - res = app.InitState("base/dslfkgjdas", "") - assert.NotEqual(res, "Success") + _, err = app.InitState("base", "dslfkgjdas", "") + require.NotNil(err) - res = app.InitState("dslfkgjdas", "") - assert.NotEqual(res, "Success") - - res = app.InitState("dslfkgjdas/szfdjzs", "") - assert.NotEqual(res, "Success") + _, err = app.InitState("", "dslfkgjdas", "") + require.NotNil(err) + _, err = app.InitState("dslfkgjdas", "szfdjzs", "") + require.NotNil(err) } // Test CheckTx and DeliverTx with insufficient and sufficient balance diff --git a/app/bc.go b/app/bc.go index 183e48bf43..b876156d89 100644 --- a/app/bc.go +++ b/app/bc.go @@ -47,23 +47,18 @@ func NewBasecoinTick(handler sdk.Handler, tick Ticker, dbName string, cacheSize // InitState - used to setup state (was SetOption) // to be used by InitChain later -func (app *Basecoin) InitState(key string, value string) string { - module, key := splitKey(key) +func (app *Basecoin) InitState(module, key, value string) (string, error) { state := app.Append() if module == ModuleNameBase { if key == ChainKey { app.info.SetChainID(state, value) - return "Success" + return "Success", nil } - return fmt.Sprintf("Error: unknown base option: %s", key) + return "", fmt.Errorf("unknown base option: %s", key) } - log, err := app.handler.InitState(app.Logger(), state, module, key, value) - if err == nil { - return log - } - return "Error: " + err.Error() + return app.handler.InitState(app.Logger(), state, module, key, value) } // DeliverTx - ABCI @@ -121,3 +116,25 @@ func (app *Basecoin) BeginBlock(req abci.RequestBeginBlock) { app.AddValChange(diff) } } + +// LoadGenesis parses the genesis file and sets the initial +// state based on that +func (app *Basecoin) LoadGenesis(filePath string) error { + init, err := GetInitialState(filePath) + if err != nil { + return err + } + + // execute all the genesis init options + // abort on any error + fmt.Printf("%#v\n", init) + for _, mkv := range init { + log, _ := app.InitState(mkv.Module, mkv.Key, mkv.Value) + // TODO: error out on bad options?? + // if err != nil { + // return err + // } + app.Logger().Info(log) + } + return nil +} diff --git a/app/genesis.go b/app/genesis.go index 81d99fead9..ceb0e1156e 100644 --- a/app/genesis.go +++ b/app/genesis.go @@ -2,33 +2,55 @@ package app import ( "encoding/json" + "strings" "github.com/pkg/errors" cmn "github.com/tendermint/tmlibs/common" ) -// LoadGenesis - Load the genesis file into memory -func (app *Basecoin) LoadGenesis(path string) error { +//nolint +const ( + ModuleNameBase = "base" +) + +// InitState just holds module/key/value triples from +// parsing the genesis file +type InitState struct { + Module string + Key string + Value string +} + +// GetInitialState parses the genesis file in a format +// that can easily be handed into InitState modules +func GetInitialState(path string) ([]InitState, error) { genDoc, err := loadGenesis(path) if err != nil { - return err + return nil, err } - // set chain_id - app.InitState("base/chain_id", genDoc.ChainID) + opts := genDoc.AppOptions + cnt := 1 + len(opts.Accounts) + len(opts.pluginOptions) + res := make([]InitState, cnt) + + res[0] = InitState{ModuleNameBase, ChainKey, genDoc.ChainID} + i := 1 // set accounts - for _, acct := range genDoc.AppOptions.Accounts { - _ = app.InitState("coin/account", string(acct)) + for _, acct := range opts.Accounts { + res[i] = InitState{"coin", "account", string(acct)} + i++ } // set plugin options - for _, kv := range genDoc.AppOptions.pluginOptions { - _ = app.InitState(kv.Key, kv.Value) + for _, kv := range opts.pluginOptions { + module, key := splitKey(kv.Key) + res[i] = InitState{module, key, kv.Value} + i++ } - return nil + return res, nil } type keyValue struct { @@ -97,3 +119,13 @@ func parseGenesisList(kvzIn []json.RawMessage) (kvz []keyValue, err error) { } return kvz, nil } + +// Splits the string at the first '/'. +// if there are none, assign default module ("base"). +func splitKey(key string) (string, string) { + if strings.Contains(key, "/") { + keyParts := strings.SplitN(key, "/", 2) + return keyParts[0], keyParts[1] + } + return ModuleNameBase, key +} diff --git a/benchmarks/app_test.go b/benchmarks/app_test.go index a849120156..690727e74a 100644 --- a/benchmarks/app_test.go +++ b/benchmarks/app_test.go @@ -69,8 +69,8 @@ func NewBenchApp(h sdk.Handler, chainID string, n int, panic(err) } - res := app.InitState("base/chain_id", chainID) - if res != "Success" { + _, err = app.InitState("base", "chain_id", chainID) + if err != nil { panic("cannot set chain") } @@ -79,8 +79,8 @@ func NewBenchApp(h sdk.Handler, chainID string, n int, accts := make([]*coin.AccountWithKey, n) for i := 0; i < n; i++ { accts[i] = coin.NewAccountWithKey(money) - res := app.InitState("coin/account", accts[i].MakeOption()) - if res != "Success" { + _, err = app.InitState("coin", "account", accts[i].MakeOption()) + if err != nil { panic("can't set account") } } diff --git a/examples/counter/plugins/counter/counter_test.go b/examples/counter/plugins/counter/counter_test.go index b9630706ef..a10e0afbbb 100644 --- a/examples/counter/plugins/counter/counter_test.go +++ b/examples/counter/plugins/counter/counter_test.go @@ -35,13 +35,14 @@ func TestCounterPlugin(t *testing.T) { logger.With("module", "app"), ) require.Nil(err, "%+v", err) - bcApp.InitState("base/chain_id", chainID) + _, err = bcApp.InitState("base", "chain_id", chainID) + require.Nil(err, "%+v", err) // Account initialization bal := coin.Coins{{"", 1000}, {"gold", 1000}} acct := coin.NewAccountWithKey(bal) - log := bcApp.InitState("coin/account", acct.MakeOption()) - require.Equal("Success", log) + _, err = bcApp.InitState("coin", "account", acct.MakeOption()) + require.Nil(err, "%+v", err) // Deliver a CounterTx DeliverCounterTx := func(valid bool, counterFee coin.Coins, sequence uint32) abci.Result {