interim gen app tx refactor
This commit is contained in:
parent
d1402f4e92
commit
12f20d160a
304
server/init.go
304
server/init.go
|
@ -4,7 +4,6 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
@ -25,59 +24,42 @@ import (
|
||||||
dbm "github.com/tendermint/tmlibs/db"
|
dbm "github.com/tendermint/tmlibs/db"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
flagOverwrite = "overwrite"
|
||||||
|
flagGenTxs = "gen-txs"
|
||||||
|
flagIP = "ip"
|
||||||
|
flagChainID = "ip"
|
||||||
|
)
|
||||||
|
|
||||||
// get cmd to initialize all files for tendermint and application
|
// get cmd to initialize all files for tendermint and application
|
||||||
func InitCmd(ctx *Context, cdc *wire.Codec, appInit AppInit) *cobra.Command {
|
func GenTxCmd(ctx *Context, cdc *wire.Codec, appInit AppInit) *cobra.Command {
|
||||||
flagOverwrite, flagPieceFile, flagIP := "overwrite", "piece-file", "ip"
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "init",
|
Use: "gen-tx",
|
||||||
Short: "Initialize genesis config, priv-validator file, and p2p-node file",
|
Short: "Create genesis transaction file (under [--home]/gentx-[nodeID].json)",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
RunE: func(_ *cobra.Command, _ []string) error {
|
RunE: func(_ *cobra.Command, args []string) error {
|
||||||
|
|
||||||
config := ctx.Config
|
config := ctx.Config
|
||||||
pubkey := ReadOrCreatePrivValidator(config)
|
|
||||||
|
|
||||||
chainID, validators, appState, cliPrint, err := appInit.GenAppParams(cdc, pubkey)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
genFile := config.GenesisFile()
|
|
||||||
if !viper.GetBool(flagOverwrite) && cmn.FileExists(genFile) {
|
|
||||||
return fmt.Errorf("genesis config file already exists: %v", genFile)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = WriteGenesisFile(cdc, genFile, chainID, validators, appState)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile())
|
nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
nodeID := string(nodeKey.ID())
|
nodeID := string(nodeKey.ID())
|
||||||
|
pubKey := ReadOrCreatePrivValidator(config)
|
||||||
|
|
||||||
// print out some key information
|
appGenTx, toPrint, validator, err := appInit.GenAppTx(cdc, pubKey)
|
||||||
|
|
||||||
toPrint := struct {
|
|
||||||
ChainID string `json:"chain_id"`
|
|
||||||
NodeID string `json:"node_id"`
|
|
||||||
AppMessage json.RawMessage `json:"app_message"`
|
|
||||||
}{
|
|
||||||
chainID,
|
|
||||||
nodeID,
|
|
||||||
cliPrint,
|
|
||||||
}
|
|
||||||
out, err := wire.MarshalJSONIndent(cdc, toPrint)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Println(string(out))
|
|
||||||
|
|
||||||
// write the piece file is path specified
|
|
||||||
if viper.GetBool(flagPieceFile) {
|
|
||||||
//create the piece
|
|
||||||
ip := viper.GetString(flagIP)
|
ip := viper.GetString(flagIP)
|
||||||
if len(ip) == 0 {
|
if len(ip) == 0 {
|
||||||
ip, err = externalIP()
|
ip, err = externalIP()
|
||||||
|
@ -85,169 +67,154 @@ func InitCmd(ctx *Context, cdc *wire.Codec, appInit AppInit) *cobra.Command {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
piece := GenesisPiece{
|
|
||||||
ChainID: chainID,
|
tx := GenesisTx{
|
||||||
NodeID: nodeID,
|
NodeID: nodeID,
|
||||||
IP: ip,
|
IP: ip,
|
||||||
AppState: appState,
|
Validator: validator,
|
||||||
Validators: validators,
|
AppGenTx: appGenTx,
|
||||||
}
|
}
|
||||||
bz, err := wire.MarshalJSONIndent(cdc, piece)
|
bz, err := wire.MarshalJSONIndent(cdc, tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
name := fmt.Sprintf("piece%v.json", nodeID)
|
name := fmt.Sprintf("gentx-%v.json", nodeID)
|
||||||
file := filepath.Join(viper.GetString("home"), name)
|
file := filepath.Join(viper.GetString("home"), name)
|
||||||
return cmn.WriteFile(file, bz, 0644)
|
if err != nil {
|
||||||
|
return err
|
||||||
|
err = cmn.WriteFile(file, bz, 0644)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out, err := wire.MarshalJSONIndent(cdc, toPrint)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println(string(out))
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if appInit.AppendAppState != nil {
|
|
||||||
cmd.AddCommand(FromPiecesCmd(ctx, cdc, appInit))
|
|
||||||
cmd.Flags().BoolP(flagPieceFile, "a", false, "create an append file (under [--home]/[nodeID]piece.json) for others to import")
|
|
||||||
}
|
|
||||||
cmd.Flags().BoolP(flagOverwrite, "o", false, "overwrite the config file")
|
|
||||||
cmd.Flags().String(flagIP, "", "external facing IP to use if left blank IP will be retrieved from this machine")
|
cmd.Flags().String(flagIP, "", "external facing IP to use if left blank IP will be retrieved from this machine")
|
||||||
cmd.Flags().AddFlagSet(appInit.Flags)
|
cmd.Flags().AddFlagSet(appInit.FlagsAppTx)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
// genesis piece structure for creating combined genesis
|
|
||||||
type GenesisPiece struct {
|
|
||||||
ChainID string `json:"chain_id"`
|
|
||||||
NodeID string `json:"node_id"`
|
|
||||||
IP string `json:"ip"`
|
|
||||||
AppState json.RawMessage `json:"app_state"`
|
|
||||||
Validators []tmtypes.GenesisValidator `json:"validators"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// get cmd to initialize all files for tendermint and application
|
// get cmd to initialize all files for tendermint and application
|
||||||
func FromPiecesCmd(ctx *Context, cdc *wire.Codec, appInit AppInit) *cobra.Command {
|
func InitCmd(ctx *Context, cdc *wire.Codec, appInit AppInit) *cobra.Command {
|
||||||
return &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "from-pieces [directory]",
|
Use: "init",
|
||||||
Short: "Create genesis from directory of genesis pieces",
|
Short: "Initialize genesis config, priv-validator file, and p2p-node file",
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.NoArgs,
|
||||||
RunE: func(_ *cobra.Command, args []string) error {
|
RunE: func(_ *cobra.Command, _ []string) error {
|
||||||
pieceDir := args[0]
|
|
||||||
|
|
||||||
// ensure that the privVal and nodeKey file already exist
|
|
||||||
config := ctx.Config
|
config := ctx.Config
|
||||||
privValFile := config.PrivValidatorFile()
|
nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile())
|
||||||
nodeKeyFile := config.NodeKeyFile()
|
|
||||||
if !cmn.FileExists(privValFile) {
|
|
||||||
return fmt.Errorf("privVal file must already exist, please initialize with init cmd: %v", privValFile)
|
|
||||||
}
|
|
||||||
if !cmn.FileExists(nodeKeyFile) {
|
|
||||||
return fmt.Errorf("nodeKey file must already exist, please initialize with init cmd: %v", nodeKeyFile)
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove genFile for creation
|
|
||||||
genFile := config.GenesisFile()
|
|
||||||
os.Remove(genFile)
|
|
||||||
|
|
||||||
// deterministically walk the directory for genesis-piece files to import
|
|
||||||
err := filepath.Walk(pieceDir, appendPiece(ctx, cdc, appInit, nodeKeyFile, genFile))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
nodeID := string(nodeKey.ID())
|
||||||
|
pubKey := ReadOrCreatePrivValidator(config)
|
||||||
|
|
||||||
|
chainID := viper.GetString(flagChainID)
|
||||||
|
if chainID == "" {
|
||||||
|
chainID = cmn.Fmt("test-chain-%v", cmn.RandStr(6))
|
||||||
|
}
|
||||||
|
|
||||||
|
genFile := config.GenesisFile()
|
||||||
|
if !viper.GetBool(flagOverwrite) && cmn.FileExists(genFile) {
|
||||||
|
return fmt.Errorf("genesis.json file already exists: %v", genFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
// process genesis transactions, or otherwise create one for defaults
|
||||||
|
var appGenTxs, cliPrints []json.RawMessage
|
||||||
|
var validators []tmtypes.GenesisValidator
|
||||||
|
var persistentPeers string
|
||||||
|
genTxsDir := viper.GetString(flagGenTxs)
|
||||||
|
if genTxsDir != "" {
|
||||||
|
validators, persistentPeers, appGenTxs, cliPrints = processGenTxs(genTxsDir, cdc, appInit)
|
||||||
|
config.P2P.PersistentPeers = persistentPeers
|
||||||
|
configFilePath := filepath.Join(viper.GetString("home"), "config", "config.toml") //TODO this is annoying should be easier to get
|
||||||
|
cfg.WriteConfigFile(configFilePath, config)
|
||||||
|
} else {
|
||||||
|
appTx, cliPrint, validator, err := appInit.GenAppTx(cdc, pubKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
validators = []tmtypes.GenesisValidator{validator}
|
||||||
|
appGenTxs = []json.RawMessage{appTx}
|
||||||
|
cliPrints = []json.RawMessage{cliPrint}
|
||||||
|
}
|
||||||
|
|
||||||
|
appState, err := appInit.GenAppParams(cdc, appGenTxs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = WriteGenesisFile(cdc, genFile, chainID, validators, appState)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// print out some key information
|
||||||
|
toPrint := struct {
|
||||||
|
ChainID string `json:"chain_id"`
|
||||||
|
NodeID string `json:"node_id"`
|
||||||
|
AppMessage []json.RawMessage `json:"app_messages"`
|
||||||
|
}{
|
||||||
|
chainID,
|
||||||
|
nodeID,
|
||||||
|
cliPrints,
|
||||||
|
}
|
||||||
|
out, err := wire.MarshalJSONIndent(cdc, toPrint)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println(string(out))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
cmd.Flags().BoolP(flagOverwrite, "o", false, "overwrite the genesis.json file")
|
||||||
|
cmd.Flags().String(flagChainID, "", "designated chain-id for the genesis")
|
||||||
|
cmd.Flags().AddFlagSet(appInit.FlagsAppParams)
|
||||||
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
// append a genesis-piece
|
// append a genesis-piece
|
||||||
func appendPiece(ctx *Context, cdc *wire.Codec, appInit AppInit, nodeKeyFile, genFile string) filepath.WalkFunc {
|
func processGenTxs(genTxsDir string, cdc *wire.Codec, appInit AppInit) (
|
||||||
return func(pieceFile string, _ os.FileInfo, err error) error {
|
validators []tmtypes.GenesisValidator, appGenTxs, cliPrints []json.RawMessage, persistentPeers string, err error) {
|
||||||
fmt.Printf("debug pieceFile: %v\n", pieceFile)
|
|
||||||
if err != nil {
|
fos, err := ioutil.ReadDir(genTxsDir)
|
||||||
return err
|
for _, fo := range fos {
|
||||||
}
|
filename := fo.Name()
|
||||||
if path.Ext(pieceFile) != ".json" {
|
if !fo.IsDir() && (path.Ext(filename) != ".json") {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the piece file bytes
|
// get the genTx
|
||||||
bz, err := ioutil.ReadFile(pieceFile)
|
bz, err := ioutil.ReadFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var genTx GenesisTx
|
||||||
|
err = cdc.UnmarshalJSON(bz, &genTx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the piece
|
// combine some stuff
|
||||||
var piece GenesisPiece
|
validators = append(validators, genTx.Validator)
|
||||||
err = cdc.UnmarshalJSON(bz, &piece)
|
appGenTxs = append(appGenTxs, genTx.AppGenTxs)
|
||||||
if err != nil {
|
cliPrints = append(cliPrints, genTx.CliPrints)
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the first file, create the genesis from scratch with piece inputs
|
// Add a persistent peer
|
||||||
if !cmn.FileExists(genFile) {
|
|
||||||
return WriteGenesisFile(cdc, genFile, piece.ChainID, piece.Validators, piece.AppState)
|
|
||||||
}
|
|
||||||
|
|
||||||
// read in the genFile
|
|
||||||
bz, err = ioutil.ReadFile(genFile)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var genMap map[string]json.RawMessage
|
|
||||||
err = cdc.UnmarshalJSON(bz, &genMap)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
appState := genMap["app_state"]
|
|
||||||
|
|
||||||
// verify chain-ids are the same
|
|
||||||
var genChainID string
|
|
||||||
err = cdc.UnmarshalJSON(genMap["chain_id"], &genChainID)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if piece.ChainID != genChainID {
|
|
||||||
return fmt.Errorf("piece chain id's are mismatched, %s != %s", piece.ChainID, genChainID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// combine the validator set
|
|
||||||
var validators []tmtypes.GenesisValidator
|
|
||||||
err = cdc.UnmarshalJSON(genMap["validators"], &validators)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
validators = append(validators, piece.Validators...)
|
|
||||||
|
|
||||||
// combine the app state
|
|
||||||
appState, err = appInit.AppendAppState(cdc, appState, piece.AppState)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// write the appended genesis file
|
|
||||||
err = WriteGenesisFile(cdc, genFile, piece.ChainID, validators, appState)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a persistent peer if the config (if it's not me)
|
|
||||||
myIP, err := externalIP()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if myIP == piece.IP {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
comma := ","
|
comma := ","
|
||||||
if len(ctx.Config.P2P.PersistentPeers) == 0 {
|
if len(persistentPeers) == 0 {
|
||||||
comma = ""
|
comma = ""
|
||||||
}
|
}
|
||||||
//newPeer := fmt.Sprintf("%s%s@%s:46656", comma, piece.NodeID, piece.IP)
|
persistentPeers += fmt.Sprintf("%s%s@%s:46656", comma, piece.NodeID, piece.IP)
|
||||||
ctx.Config.P2P.PersistentPeers += fmt.Sprintf("%s%s@%s:46656", comma, piece.NodeID, piece.IP)
|
}
|
||||||
configFilePath := filepath.Join(viper.GetString("home"), "config", "config.toml") //TODO this is annoying should be easier to get
|
|
||||||
cfg.WriteConfigFile(configFilePath, ctx.Config)
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//________________________________________________________________________________________
|
//________________________________________________________________________________________
|
||||||
|
@ -299,15 +266,17 @@ func addAppStateToGenesis(cdc *wire.Codec, genesisConfigPath string, appState js
|
||||||
// Core functionality passed from the application to the server init command
|
// Core functionality passed from the application to the server init command
|
||||||
type AppInit struct {
|
type AppInit struct {
|
||||||
|
|
||||||
// flags required for GenAppParams
|
// flags required for application init functions
|
||||||
Flags *pflag.FlagSet
|
FlagsAppParams *pflag.FlagSet
|
||||||
|
FlagsAppTx *pflag.FlagSet
|
||||||
|
|
||||||
// GenAppParams creates the core parameters initialization. It takes in a
|
// GenAppParams creates the core parameters initialization. It takes in a
|
||||||
// pubkey meant to represent the pubkey of the validator of this machine.
|
// pubkey meant to represent the pubkey of the validator of this machine.
|
||||||
GenAppParams func(*wire.Codec, crypto.PubKey) (chainID string, validators []tmtypes.GenesisValidator, appState, cliPrint json.RawMessage, err error)
|
GenAppParams func(cdc *wire.Codec, appGenTxs []json.RawMessage) (appState json.RawMessage, err error)
|
||||||
|
|
||||||
// append appState1 with appState2
|
// create the application genesis tx
|
||||||
AppendAppState func(cdc *wire.Codec, appState1, appState2 json.RawMessage) (appState json.RawMessage, err error)
|
GenAppTx func(cdc *wire.Codec, pk crypto.PubKey) (
|
||||||
|
appTx, cliPrint json.RawMessage, validator tmtypes.GenesisValidator, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// simple default application init
|
// simple default application init
|
||||||
|
@ -316,7 +285,8 @@ var DefaultAppInit = AppInit{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create one account with a whole bunch of mycoin in it
|
// Create one account with a whole bunch of mycoin in it
|
||||||
func SimpleGenAppParams(cdc *wire.Codec, pubKey crypto.PubKey) (chainID string, validators []tmtypes.GenesisValidator, appState, cliPrint json.RawMessage, err error) {
|
func SimpleGenAppParams(cdc *wire.Codec, pubKey crypto.PubKey, _ json.RawMessage) (
|
||||||
|
validators []tmtypes.GenesisValidator, appState, cliPrint json.RawMessage, err error) {
|
||||||
|
|
||||||
var addr sdk.Address
|
var addr sdk.Address
|
||||||
|
|
||||||
|
@ -330,8 +300,6 @@ func SimpleGenAppParams(cdc *wire.Codec, pubKey crypto.PubKey) (chainID string,
|
||||||
bz, err := cdc.MarshalJSON(mm)
|
bz, err := cdc.MarshalJSON(mm)
|
||||||
cliPrint = json.RawMessage(bz)
|
cliPrint = json.RawMessage(bz)
|
||||||
|
|
||||||
chainID = cmn.Fmt("test-chain-%v", cmn.RandStr(6))
|
|
||||||
|
|
||||||
validators = []tmtypes.GenesisValidator{{
|
validators = []tmtypes.GenesisValidator{{
|
||||||
PubKey: pubKey,
|
PubKey: pubKey,
|
||||||
Power: 10,
|
Power: 10,
|
||||||
|
|
Loading…
Reference in New Issue