package server import ( "encoding/json" "fmt" "github.com/cosmos/cosmos-sdk/crypto/keys" "github.com/pkg/errors" "github.com/spf13/pflag" "github.com/tendermint/tendermint/crypto" dbm "github.com/tendermint/tendermint/libs/db" tmtypes "github.com/tendermint/tendermint/types" clkeys "github.com/cosmos/cosmos-sdk/client/keys" "github.com/cosmos/cosmos-sdk/codec" serverconfig "github.com/cosmos/cosmos-sdk/server/config" sdk "github.com/cosmos/cosmos-sdk/types" ) //Parameter names, for init gen-tx command var ( FlagName = "name" FlagClientHome = "home-client" FlagOWK = "owk" ) //parameter names, init command var ( FlagOverwrite = "overwrite" FlagWithTxs = "with-txs" FlagIP = "ip" FlagChainID = "chain-id" ) // genesis piece structure for creating combined genesis type GenesisTx struct { NodeID string `json:"node_id"` IP string `json:"ip"` Validator tmtypes.GenesisValidator `json:"validator"` AppGenTx json.RawMessage `json:"app_gen_tx"` } // Storage for init command input parameters type InitConfig struct { ChainID string GenTxs bool GenTxsDir string Overwrite bool } //________________________________________________________________________________________ //_____________________________________________________________________ // Core functionality passed from the application to the server init command type AppInit struct { // flags required for application init functions FlagsAppGenState *pflag.FlagSet FlagsAppGenTx *pflag.FlagSet // create the application genesis tx AppGenTx func(cdc *codec.Codec, pk crypto.PubKey, genTxConfig serverconfig.GenTx) ( appGenTx, cliPrint json.RawMessage, validator tmtypes.GenesisValidator, err error) // AppGenState creates the core parameters initialization. It takes in a // pubkey meant to represent the pubkey of the validator of this machine. AppGenState func(cdc *codec.Codec, appGenTxs []json.RawMessage) (appState json.RawMessage, err error) } //_____________________________________________________________________ // simple default application init var DefaultAppInit = AppInit{ AppGenTx: SimpleAppGenTx, AppGenState: SimpleAppGenState, } // simple genesis tx type SimpleGenTx struct { Addr sdk.AccAddress `json:"addr"` } // Generate a genesis transaction func SimpleAppGenTx(cdc *codec.Codec, pk crypto.PubKey, genTxConfig serverconfig.GenTx) ( appGenTx, cliPrint json.RawMessage, validator tmtypes.GenesisValidator, err error) { var addr sdk.AccAddress var secret string addr, secret, err = GenerateCoinKey() if err != nil { return } var bz []byte simpleGenTx := SimpleGenTx{addr} bz, err = cdc.MarshalJSON(simpleGenTx) if err != nil { return } appGenTx = json.RawMessage(bz) mm := map[string]string{"secret": secret} bz, err = cdc.MarshalJSON(mm) if err != nil { return } cliPrint = json.RawMessage(bz) validator = tmtypes.GenesisValidator{ PubKey: pk, Power: 10, } return } // create the genesis app state func SimpleAppGenState(cdc *codec.Codec, appGenTxs []json.RawMessage) (appState json.RawMessage, err error) { if len(appGenTxs) != 1 { err = errors.New("must provide a single genesis transaction") return } var genTx SimpleGenTx err = cdc.UnmarshalJSON(appGenTxs[0], &genTx) if err != nil { return } appState = json.RawMessage(fmt.Sprintf(`{ "accounts": [{ "address": "%s", "coins": [ { "denom": "mycoin", "amount": "9007199254740992" } ] }] }`, genTx.Addr)) return } //___________________________________________________________________________________________ // GenerateCoinKey returns the address of a public key, along with the secret // phrase to recover the private key. func GenerateCoinKey() (sdk.AccAddress, string, error) { // construct an in-memory key store keybase := keys.New( dbm.NewMemDB(), ) // generate a private key, with recovery phrase info, secret, err := keybase.CreateMnemonic("name", keys.English, "pass", keys.Secp256k1) if err != nil { return sdk.AccAddress([]byte{}), "", err } addr := info.GetPubKey().Address() return sdk.AccAddress(addr), secret, nil } // GenerateSaveCoinKey returns the address of a public key, along with the secret // phrase to recover the private key. func GenerateSaveCoinKey(clientRoot, keyName, keyPass string, overwrite bool) (sdk.AccAddress, string, error) { // get the keystore from the client keybase, err := clkeys.GetKeyBaseFromDir(clientRoot) if err != nil { return sdk.AccAddress([]byte{}), "", err } // ensure no overwrite if !overwrite { _, err := keybase.Get(keyName) if err == nil { return sdk.AccAddress([]byte{}), "", errors.New("key already exists, overwrite is disabled") } } // generate a private key, with recovery phrase info, secret, err := keybase.CreateMnemonic(keyName, keys.English, keyPass, keys.Secp256k1) if err != nil { return sdk.AccAddress([]byte{}), "", err } addr := info.GetPubKey().Address() return sdk.AccAddress(addr), secret, nil }