Separate genesis parsing from basecoin

This commit is contained in:
Ethan Frey 2017-10-16 17:34:29 +02:00
parent c1d36eeb21
commit df0f3a22da
6 changed files with 93 additions and 55 deletions

View File

@ -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 == "" {

View File

@ -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

View File

@ -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
}

View File

@ -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
}

View File

@ -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")
}
}

View File

@ -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 {