From c8f5fcb27b26d2a4132d6871ccfbf670b09f4fef Mon Sep 17 00:00:00 2001 From: rigelrozanski Date: Mon, 23 Apr 2018 15:15:50 -0400 Subject: [PATCH] init append functionality complete --- server/init.go | 48 ++++++++++++++++++++++++++++++++++++++------ server/init_test.go | 4 +++- server/start_test.go | 7 +++++-- server/util.go | 41 +++++++++++++++++++++++++++++++++++++ server/util_test.go | 2 +- 5 files changed, 92 insertions(+), 10 deletions(-) diff --git a/server/init.go b/server/init.go index 0ce6ad50b..3e8e0da4a 100644 --- a/server/init.go +++ b/server/init.go @@ -27,7 +27,7 @@ import ( // TODO flag to retrieve genesis file / config file from a URL? // get cmd to initialize all files for tendermint and application func InitCmd(ctx *Context, cdc *wire.Codec, gen GenAppParams, appendState AppendAppState) *cobra.Command { - flagOverwrite, flagAppendFile := "overwrite", "piece-file" + flagOverwrite, flagPieceFile := "overwrite", "piece-file" cmd := &cobra.Command{ Use: "init", Short: "Initialize genesis config, priv-validator file, and p2p-node file", @@ -56,15 +56,17 @@ func InitCmd(ctx *Context, cdc *wire.Codec, gen GenAppParams, appendState Append if err != nil { return err } + nodeID := string(nodeKey.ID()) // print out some key information + toPrint := struct { ChainID string `json:"chain_id"` NodeID string `json:"node_id"` AppMessage json.RawMessage `json:"app_message"` }{ chainID, - string(nodeKey.ID()), + nodeID, cliPrint, } out, err := wire.MarshalJSONIndent(cdc, toPrint) @@ -72,12 +74,35 @@ func InitCmd(ctx *Context, cdc *wire.Codec, gen GenAppParams, appendState Append return err } fmt.Println(string(out)) + + // write the piece file is path specified + pieceFile := viper.GetString(flagPieceFile) + if len(pieceFile) > 0 { + //create the piece + ip, err := externalIP() + if err != nil { + return err + } + piece := GenesisPiece{ + ChainID: chainID, + NodeID: nodeID, + IP: ip, + AppState: appState, + Validators: validators, + } + bz, err := cdc.MarshalJSON(piece) + if err != nil { + return err + } + return cmn.WriteFile(pieceFile, bz, 0644) + } + return nil }, } if appendState != nil { cmd.AddCommand(FromPiecesCmd(ctx, cdc, appendState)) - cmd.Flags().BoolP(flagAppendFile, "a", false, "create an append file for others to import") + cmd.Flags().StringP(flagPieceFile, "a", "", "create an append file for others to import") } cmd.Flags().BoolP(flagOverwrite, "o", false, "overwrite the config file") return cmd @@ -87,6 +112,7 @@ func InitCmd(ctx *Context, cdc *wire.Codec, gen GenAppParams, appendState Append 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"` } @@ -116,7 +142,7 @@ func FromPiecesCmd(ctx *Context, cdc *wire.Codec, appendState AppendAppState) *c os.Remove(genFile) // deterministically walk the directory for genesis-piece files to import - filepath.Walk(pieceDir, appendPiece(cdc, appendState, nodeKeyFile, genFile)) + filepath.Walk(pieceDir, appendPiece(ctx, cdc, appendState, nodeKeyFile, genFile)) return nil }, @@ -124,7 +150,7 @@ func FromPiecesCmd(ctx *Context, cdc *wire.Codec, appendState AppendAppState) *c } // append a genesis-piece -func appendPiece(cdc *wire.Codec, appendState AppendAppState, nodeKeyFile, genFile string) filepath.WalkFunc { +func appendPiece(ctx *Context, cdc *wire.Codec, appendState AppendAppState, nodeKeyFile, genFile string) filepath.WalkFunc { return func(pieceFile string, _ os.FileInfo, err error) error { if err != nil { return err @@ -185,7 +211,17 @@ func appendPiece(cdc *wire.Codec, appendState AppendAppState, nodeKeyFile, genFi // write the appended genesis file return WriteGenesisFile(cdc, genFile, piece.ChainID, validators, appState) - // XXX XXX XXX read in configTOMBL and combine new nodeID file + // 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 + } + ctx.Config.P2P.PersistentPeers += fmt.Sprintf(",%s@%s", 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 } diff --git a/server/init_test.go b/server/init_test.go index e4bf8c016..b13fb4789 100644 --- a/server/init_test.go +++ b/server/init_test.go @@ -8,6 +8,7 @@ import ( "github.com/tendermint/tmlibs/log" "github.com/cosmos/cosmos-sdk/mock" + "github.com/cosmos/cosmos-sdk/wire" tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" ) @@ -18,7 +19,8 @@ func TestInit(t *testing.T) { cfg, err := tcmd.ParseConfig() require.Nil(t, err) ctx := NewContext(cfg, logger) - cmd := InitCmd(ctx, cdc, mock.GenAppParams) + cdc := wire.NewCodec() + cmd := InitCmd(ctx, cdc, mock.GenAppParams, nil) err = cmd.RunE(nil, nil) require.NoError(t, err) } diff --git a/server/start_test.go b/server/start_test.go index 9cbd45661..d933d19f1 100644 --- a/server/start_test.go +++ b/server/start_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "github.com/cosmos/cosmos-sdk/mock" + "github.com/cosmos/cosmos-sdk/wire" "github.com/tendermint/abci/server" tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" "github.com/tendermint/tmlibs/log" @@ -25,7 +26,8 @@ func TestStartStandAlone(t *testing.T) { cfg, err := tcmd.ParseConfig() require.Nil(t, err) ctx := NewContext(cfg, logger) - initCmd := InitCmd(ctx, cdc, mock.GenAppParams) + cdc := wire.NewCodec() + initCmd := InitCmd(ctx, cdc, mock.GenAppParams, nil) err = initCmd.RunE(nil, nil) require.NoError(t, err) @@ -51,7 +53,8 @@ func TestStartWithTendermint(t *testing.T) { cfg, err := tcmd.ParseConfig() require.Nil(t, err) ctx := NewContext(cfg, logger) - initCmd := InitCmd(ctx, cdc, mock.GenAppParams) + cdc := wire.NewCodec() + initCmd := InitCmd(ctx, cdc, mock.GenAppParams, nil) err = initCmd.RunE(nil, nil) require.NoError(t, err) diff --git a/server/util.go b/server/util.go index 4b34d0383..3f24d5987 100644 --- a/server/util.go +++ b/server/util.go @@ -2,8 +2,10 @@ package server import ( "encoding/json" + "net" "os" + "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -93,3 +95,42 @@ func AppendJSON(cdc *wire.Codec, baseJSON []byte, key string, value json.RawMess bz, err := wire.MarshalJSONIndent(cdc, jsonMap) return json.RawMessage(bz), err } + +// https://stackoverflow.com/questions/23558425/how-do-i-get-the-local-ip-address-in-go +// TODO there must be a better way to get external IP +func externalIP() (string, error) { + ifaces, err := net.Interfaces() + if err != nil { + return "", err + } + for _, iface := range ifaces { + if iface.Flags&net.FlagUp == 0 { + continue // interface down + } + if iface.Flags&net.FlagLoopback != 0 { + continue // loopback interface + } + addrs, err := iface.Addrs() + if err != nil { + return "", err + } + for _, addr := range addrs { + var ip net.IP + switch v := addr.(type) { + case *net.IPNet: + ip = v.IP + case *net.IPAddr: + ip = v.IP + } + if ip == nil || ip.IsLoopback() { + continue + } + ip = ip.To4() + if ip == nil { + continue // not an ipv4 address + } + return ip.String(), nil + } + } + return "", errors.New("are you connected to the network?") +} diff --git a/server/util_test.go b/server/util_test.go index 5345b0f8f..a21fe3882 100644 --- a/server/util_test.go +++ b/server/util_test.go @@ -12,6 +12,7 @@ import ( //func AppendJSON(cdc *wire.Codec, baseJSON []byte, key string, value json.RawMessage) (appended []byte, err error) { func TestAppendJSON(t *testing.T) { + cdc := wire.NewCodec() foo := map[string]string{"foo": "foofoo"} bar := map[string]string{"barInner": "barbar"} @@ -26,7 +27,6 @@ func TestAppendJSON(t *testing.T) { barRaw := json.RawMessage(bz) // make the append - cdc := wire.NewCodec() appBz, err := AppendJSON(cdc, fooRaw, "barOuter", barRaw) require.NoError(t, err)