cosmos-sdk/_attic/genesis/parse.go

154 lines
3.6 KiB
Go
Raw Normal View History

package genesis
2017-01-28 09:29:32 -08:00
import (
"encoding/json"
2017-10-16 08:34:29 -07:00
"strings"
2017-01-28 09:29:32 -08:00
sdk "github.com/cosmos/cosmos-sdk"
2017-01-28 09:29:32 -08:00
"github.com/pkg/errors"
2017-05-13 17:04:53 -07:00
2017-04-25 22:08:31 -07:00
cmn "github.com/tendermint/tmlibs/common"
2017-01-28 09:29:32 -08:00
)
2017-10-20 04:45:54 -07:00
// KeyDelimiter is used to separate module and key in
// the options
const KeyDelimiter = "/"
2017-10-16 09:31:07 -07:00
// Option just holds module/key/value triples from
2017-10-16 08:34:29 -07:00
// parsing the genesis file
2017-10-16 09:31:07 -07:00
type Option struct {
2017-10-16 08:34:29 -07:00
Module string
Key string
Value string
}
2017-10-16 09:31:07 -07:00
// InitStater is anything that can handle app options
// from genesis file. Setting the merkle store, config options,
// or anything else
2017-10-16 09:31:07 -07:00
type InitStater interface {
InitState(module, key, value string) error
2017-10-16 09:31:07 -07:00
}
2017-10-17 06:51:13 -07:00
// Load parses the genesis file and sets the initial
2017-10-16 09:31:07 -07:00
// state based on that
2017-10-17 06:51:13 -07:00
func Load(app InitStater, filePath string) error {
opts, err := GetOptions(filePath)
2017-10-16 09:31:07 -07:00
if err != nil {
return err
}
// execute all the genesis init options
// abort on any error
for _, opt := range opts {
err = app.InitState(opt.Module, opt.Key, opt.Value)
if err != nil {
return err
}
2017-10-16 09:31:07 -07:00
}
return nil
}
2017-10-17 06:51:13 -07:00
// GetOptions parses the genesis file in a format
2017-10-16 09:31:07 -07:00
// that can easily be handed into InitStaters
2017-10-17 06:51:13 -07:00
func GetOptions(path string) ([]Option, error) {
genDoc, err := load(path)
2017-01-28 09:29:32 -08:00
if err != nil {
2017-10-16 08:34:29 -07:00
return nil, err
2017-01-28 09:29:32 -08:00
}
2017-03-14 00:11:49 -07:00
2017-10-16 08:34:29 -07:00
opts := genDoc.AppOptions
cnt := 1 + len(opts.Accounts) + len(opts.pluginOptions)
2017-10-19 08:44:22 -07:00
res := make([]Option, 0, cnt)
res = append(res, Option{sdk.ModuleNameBase, sdk.ChainKey, genDoc.ChainID})
2017-03-14 10:55:46 -07:00
// set accounts
2017-10-16 08:34:29 -07:00
for _, acct := range opts.Accounts {
2017-10-19 08:44:22 -07:00
res = append(res, Option{"coin", "account", string(acct)})
2017-03-14 10:55:46 -07:00
}
// set plugin options
2017-10-16 08:34:29 -07:00
for _, kv := range opts.pluginOptions {
module, key := splitKey(kv.Key)
2017-10-19 08:44:22 -07:00
res = append(res, Option{module, key, kv.Value})
2017-01-28 09:29:32 -08:00
}
2017-10-16 08:34:29 -07:00
return res, nil
2017-01-28 09:29:32 -08:00
}
type keyValue struct {
Key string `json:"key"`
Value string `json:"value"`
}
2017-10-17 06:51:13 -07:00
// FullDoc - includes tendermint (in the json, we ignore here)
type FullDoc struct {
ChainID string `json:"chain_id"`
AppOptions *Doc `json:"app_options"`
2017-03-14 00:11:49 -07:00
}
2017-10-17 06:51:13 -07:00
// Doc - All genesis values
type Doc struct {
2017-07-03 09:58:28 -07:00
Accounts []json.RawMessage `json:"accounts"`
2017-03-14 10:55:46 -07:00
PluginOptions []json.RawMessage `json:"plugin_options"`
pluginOptions []keyValue // unmarshaled rawmessages
2017-03-14 00:11:49 -07:00
}
2017-10-17 06:51:13 -07:00
func load(filePath string) (*FullDoc, error) {
2017-01-28 09:29:32 -08:00
bytes, err := cmn.ReadFile(filePath)
if err != nil {
2017-03-14 10:55:46 -07:00
return nil, errors.Wrap(err, "loading genesis file")
2017-01-28 09:29:32 -08:00
}
2017-03-14 00:11:49 -07:00
2017-04-25 22:08:31 -07:00
// the basecoin genesis go-wire/data :)
2017-10-17 06:51:13 -07:00
genDoc := new(FullDoc)
2017-03-14 10:55:46 -07:00
err = json.Unmarshal(bytes, genDoc)
if err != nil {
return nil, errors.Wrap(err, "unmarshaling genesis file")
}
if genDoc.AppOptions == nil {
2017-10-17 06:51:13 -07:00
genDoc.AppOptions = new(Doc)
}
2017-10-17 06:51:13 -07:00
pluginOpts, err := parseList(genDoc.AppOptions.PluginOptions)
2017-01-28 09:29:32 -08:00
if err != nil {
2017-03-14 10:55:46 -07:00
return nil, err
2017-01-28 09:29:32 -08:00
}
2017-03-14 10:55:46 -07:00
genDoc.AppOptions.pluginOptions = pluginOpts
return genDoc, nil
2017-03-14 00:11:49 -07:00
}
2017-10-17 06:51:13 -07:00
func parseList(kvzIn []json.RawMessage) (kvz []keyValue, err error) {
2017-07-04 20:28:27 -07:00
if len(kvzIn)%2 != 0 {
2017-01-28 09:29:32 -08:00
return nil, errors.New("genesis cannot have an odd number of items. Format = [key1, value1, key2, value2, ...]")
}
2017-02-24 14:25:48 -08:00
2017-07-04 20:28:27 -07:00
for i := 0; i < len(kvzIn); i += 2 {
2017-02-24 14:25:48 -08:00
kv := keyValue{}
2017-07-04 20:28:27 -07:00
rawK := []byte(kvzIn[i])
2017-02-24 14:25:48 -08:00
err := json.Unmarshal(rawK, &(kv.Key))
if err != nil {
return nil, errors.Errorf("Non-string key: %s", string(rawK))
2017-01-28 09:29:32 -08:00
}
2017-02-24 14:25:48 -08:00
// convert value to string if possible (otherwise raw json)
2017-07-04 20:28:27 -07:00
rawV := kvzIn[i+1]
2017-02-24 14:25:48 -08:00
err = json.Unmarshal(rawV, &(kv.Value))
if err != nil {
kv.Value = string(rawV)
2017-01-28 09:29:32 -08:00
}
2017-02-24 14:25:48 -08:00
kvz = append(kvz, kv)
2017-01-28 09:29:32 -08:00
}
return kvz, nil
}
2017-10-16 08:34:29 -07:00
// Splits the string at the first '/'.
// if there are none, assign default module ("base").
func splitKey(key string) (string, string) {
2017-10-20 04:45:54 -07:00
if strings.Contains(key, KeyDelimiter) {
keyParts := strings.SplitN(key, KeyDelimiter, 2)
2017-10-16 08:34:29 -07:00
return keyParts[0], keyParts[1]
}
return sdk.ModuleNameBase, key
2017-10-16 08:34:29 -07:00
}