OSDN Git Service

P2P: fixed node startup id (#1573)
authoryahtoo <yahtoo.ma@gmail.com>
Wed, 20 Feb 2019 04:06:43 +0000 (12:06 +0800)
committerPaladz <yzhu101@uottawa.ca>
Wed, 20 Feb 2019 04:06:43 +0000 (12:06 +0800)
* P2P: fixed node startup id

* Add test file

* Fix test error

* Fix review bug

* Fix test error

* Add log info

cmd/bytomd/commands/run_node.go
config/config.go
config/config_test.go
p2p/switch.go
p2p/switch_test.go
p2p/test_util.go
vendor/github.com/tendermint/go-crypto/priv_key.go

index 587b2c5..f38407d 100644 (file)
@@ -38,6 +38,7 @@ func init() {
        // p2p flags
        runNodeCmd.Flags().String("p2p.laddr", config.P2P.ListenAddress, "Node listen address. (0.0.0.0:0 means any interface, any port)")
        runNodeCmd.Flags().String("p2p.seeds", config.P2P.Seeds, "Comma delimited host:port seed nodes")
+       runNodeCmd.Flags().String("p2p.node_key", config.P2P.PrivateKey, "Node key for p2p communication")
        runNodeCmd.Flags().Bool("p2p.skip_upnp", config.P2P.SkipUPNP, "Skip UPNP configuration")
        runNodeCmd.Flags().Int("p2p.max_num_peers", config.P2P.MaxNumPeers, "Set max num peers")
        runNodeCmd.Flags().Int("p2p.handshake_timeout", config.P2P.HandshakeTimeout, "Set handshake timeout")
index c5500c2..2e2990f 100644 (file)
@@ -1,12 +1,15 @@
 package config
 
 import (
+       "io"
+       "io/ioutil"
        "os"
        "os/user"
        "path/filepath"
        "runtime"
 
        log "github.com/sirupsen/logrus"
+       "github.com/tendermint/go-crypto"
 )
 
 var (
@@ -47,6 +50,34 @@ func (cfg *Config) SetRoot(root string) *Config {
        return cfg
 }
 
+// NodeKey retrieves the currently configured private key of the node, checking
+// first any manually set key, falling back to the one found in the configured
+// data folder. If no key can be found, a new one is generated.
+func (cfg *Config) NodeKey() (string, error) {
+       // Use any specifically configured key.
+       if cfg.P2P.PrivateKey != "" {
+               return cfg.P2P.PrivateKey, nil
+       }
+
+       keyFile := rootify(cfg.P2P.NodeKeyFile, cfg.BaseConfig.RootDir)
+       buf := make([]byte, len(crypto.PrivKeyEd25519{})*2)
+       fd, err := os.Open(keyFile)
+       defer fd.Close()
+       if err == nil {
+               if _, err = io.ReadFull(fd, buf); err == nil {
+                       return string(buf), nil
+               }
+       }
+
+       log.WithField("err", err).Warning("key file access failed")
+       privKey := crypto.GenPrivKeyEd25519()
+       if err = ioutil.WriteFile(keyFile, []byte(privKey.String()), 0600); err != nil {
+               return "", err
+       }
+
+       return privKey.String(), nil
+}
+
 //-----------------------------------------------------------------------------
 // BaseConfig
 type BaseConfig struct {
@@ -106,6 +137,8 @@ func (b BaseConfig) KeysDir() string {
 type P2PConfig struct {
        ListenAddress    string `mapstructure:"laddr"`
        Seeds            string `mapstructure:"seeds"`
+       PrivateKey       string `mapstructure:"node_key"`
+       NodeKeyFile      string `mapstructure:"node_key_file"`
        SkipUPNP         bool   `mapstructure:"skip_upnp"`
        MaxNumPeers      int    `mapstructure:"max_num_peers"`
        HandshakeTimeout int    `mapstructure:"handshake_timeout"`
@@ -119,6 +152,7 @@ type P2PConfig struct {
 func DefaultP2PConfig() *P2PConfig {
        return &P2PConfig{
                ListenAddress:    "tcp://0.0.0.0:46656",
+               NodeKeyFile:      "nodekey",
                SkipUPNP:         false,
                MaxNumPeers:      50,
                HandshakeTimeout: 30,
index f324d40..280f47e 100644 (file)
@@ -1,6 +1,9 @@
 package config
 
 import (
+       "io/ioutil"
+       "os"
+       "strings"
        "testing"
 
        "github.com/stretchr/testify/assert"
@@ -20,3 +23,38 @@ func TestDefaultConfig(t *testing.T) {
        assert.Equal("/opt/data", cfg.DBDir())
 
 }
+
+func TestNodeKey(t *testing.T) {
+       tmpDir, err := ioutil.TempDir(".", "")
+       if err != nil {
+               t.Fatalf("failed to create temporary data folder: %v", err)
+       }
+       defer os.RemoveAll(tmpDir)
+       config := DefaultConfig()
+       config.BaseConfig.RootDir = tmpDir
+
+       config.P2P.PrivateKey = "0fcbd0be11e35c35c41c686b7ca597bbcf8ecb78e320d01a93349c8ce9420ea4f26d0fbe651bb2c248d6727801329b589ed19e384c9e906d1da4ab2360558bc0"
+       privKey, err := config.NodeKey()
+       if err != nil {
+               t.Fatal("test node key error:", err)
+       }
+
+       if strings.Compare(privKey, config.P2P.PrivateKey) != 0 {
+               t.Fatal("test node key error. want:", config.P2P.PrivateKey, "got:", privKey)
+       }
+
+       config.P2P.PrivateKey = ""
+       writePrivKey, err := config.NodeKey()
+       if err != nil {
+               t.Fatal("test node key error:", err)
+       }
+
+       readPrivKey, err := config.NodeKey()
+       if err != nil {
+               t.Fatal("test node key error:", err)
+       }
+
+       if strings.Compare(writePrivKey, readPrivKey) != 0 {
+               t.Fatal("test node key error. write:", writePrivKey, "read:", readPrivKey)
+       }
+}
index 0643cbc..ec4b73d 100644 (file)
@@ -1,6 +1,7 @@
 package p2p
 
 import (
+       "encoding/hex"
        "encoding/json"
        "fmt"
        "net"
@@ -64,12 +65,25 @@ type Switch struct {
 
 // NewSwitch create a new Switch and set discover.
 func NewSwitch(config *cfg.Config) (*Switch, error) {
-       blacklistDB := dbm.NewDB("trusthistory", config.DBBackend, config.DBDir())
-       privKey := crypto.GenPrivKeyEd25519()
+       var err error
        var l Listener
        var listenAddr string
-       var err error
        var discv *discover.Network
+
+       blacklistDB := dbm.NewDB("trusthistory", config.DBBackend, config.DBDir())
+       config.P2P.PrivateKey, err = config.NodeKey()
+       if err != nil {
+               return nil, err
+       }
+
+       bytes, err := hex.DecodeString(config.P2P.PrivateKey)
+       if err != nil {
+               return nil, err
+       }
+
+       var newKey [64]byte
+       copy(newKey[:], bytes)
+       privKey := crypto.PrivKeyEd25519(newKey)
        if !config.VaultMode {
                // Create listener
                l, listenAddr = GetListener(config.P2P)
@@ -79,11 +93,11 @@ func NewSwitch(config *cfg.Config) (*Switch, error) {
                }
        }
 
-       return newSwitch(discv, blacklistDB, l, config, privKey, listenAddr)
+       return newSwitch(config, discv, blacklistDB, l, privKey, listenAddr)
 }
 
 // newSwitch creates a new Switch with the given config.
-func newSwitch(discv discv, blacklistDB dbm.DB, l Listener, config *cfg.Config, priv crypto.PrivKeyEd25519, listenAddr string) (*Switch, error) {
+func newSwitch(config *cfg.Config, discv discv, blacklistDB dbm.DB, l Listener, priv crypto.PrivKeyEd25519, listenAddr string) (*Switch, error) {
        sw := &Switch{
                Config:       config,
                peerConfig:   DefaultPeerConfig(config.P2P),
index ce505a5..3851521 100644 (file)
@@ -1,14 +1,12 @@
 package p2p
 
 import (
+       "github.com/tendermint/go-crypto"
+       dbm "github.com/tendermint/tmlibs/db"
        "io/ioutil"
        "os"
        "sync"
        "testing"
-       "time"
-
-       "github.com/tendermint/go-crypto"
-       dbm "github.com/tendermint/tmlibs/db"
 
        cfg "github.com/bytom/config"
        "github.com/bytom/errors"
@@ -145,7 +143,7 @@ func TestFiltersOutItself(t *testing.T) {
        }
 
        //S1 dialing itself ip address
-       addr, err := NewNetAddressString(s1.NodeInfo().ListenAddr)
+       addr, err := NewNetAddressString("0.0.0.0:46656")
        if err != nil {
                t.Fatal(err)
        }
@@ -180,7 +178,7 @@ func TestDialBannedPeer(t *testing.T) {
        }
 }
 
-func TestDuplicatePeer(t *testing.T) {
+func TestDuplicateOutBoundPeer(t *testing.T) {
        dirPath, err := ioutil.TempDir(".", "")
        if err != nil {
                t.Fatal(err)
@@ -201,9 +199,22 @@ func TestDuplicatePeer(t *testing.T) {
        if err = s1.DialPeerWithAddress(rp.addr); errors.Root(err) != ErrDuplicatePeer {
                t.Fatal(err)
        }
+}
+
+func TestDuplicateInBoundPeer(t *testing.T) {
+       dirPath, err := ioutil.TempDir(".", "")
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer os.RemoveAll(dirPath)
+
+       testDB := dbm.NewDB("testdb", "leveldb", dirPath)
+       s1 := MakeSwitch(testCfg, testDB, initSwitchFunc)
+       s1.Start()
+       defer s1.Stop()
 
        inp := &inboundPeer{PrivKey: crypto.GenPrivKeyEd25519(), config: testCfg}
-       addr, err := NewNetAddressString(s1.NodeInfo().ListenAddr)
+       addr, err := NewNetAddressString(s1.nodeInfo.ListenAddr)
        if err != nil {
                t.Fatal(err)
        }
@@ -218,9 +229,8 @@ func TestDuplicatePeer(t *testing.T) {
                t.Fatal(err)
        }
 
-       time.Sleep(1 * time.Second)
-       if outbound, inbound, dialing := s1.NumPeers(); outbound+inbound+dialing != 2 {
-               t.Fatal("TestSwitchAddInboundPeer peer size error")
+       if outbound, inbound, dialing := s1.NumPeers(); outbound+inbound+dialing != 1 {
+               t.Fatal("TestSwitchAddInboundPeer peer size error", outbound, inbound, dialing)
        }
 }
 
@@ -239,7 +249,7 @@ func TestAddInboundPeer(t *testing.T) {
        defer s1.Stop()
 
        inp := &inboundPeer{PrivKey: crypto.GenPrivKeyEd25519(), config: testCfg}
-       addr, err := NewNetAddressString(s1.NodeInfo().ListenAddr)
+       addr, err := NewNetAddressString(s1.nodeInfo.ListenAddr)
        if err != nil {
                t.Fatal(err)
        }
@@ -280,7 +290,7 @@ func TestStopPeer(t *testing.T) {
        defer s1.Stop()
 
        inp := &inboundPeer{PrivKey: crypto.GenPrivKeyEd25519(), config: testCfg}
-       addr, err := NewNetAddressString(s1.NodeInfo().ListenAddr)
+       addr, err := NewNetAddressString("127.0.0.1:46656")
        if err != nil {
                t.Fatal(err)
        }
index 02a300d..1812843 100644 (file)
@@ -121,7 +121,7 @@ func MakeSwitch(cfg *cfg.Config, testdb dbm.DB, initSwitch func(*Switch) *Switch
        // TODO: let the config be passed in?
        privKey := crypto.GenPrivKeyEd25519()
        l, listenAddr := GetListener(cfg.P2P)
-       sw, err := newSwitch(new(mockDiscv), testdb, l, cfg, privKey, listenAddr)
+       sw, err := newSwitch(cfg, new(mockDiscv), testdb, l, privKey, listenAddr)
        if err != nil {
                log.Errorf("create switch error: %s", err)
                return nil
index 233563f..accc773 100644 (file)
@@ -1,10 +1,11 @@
 package crypto
 
 import (
+       "encoding/hex"
+
        "github.com/tendermint/ed25519"
        "github.com/tendermint/go-wire"
-       data "github.com/tendermint/go-wire/data"
-       . "github.com/tendermint/tmlibs/common"
+       "github.com/tendermint/go-wire/data"
 )
 
 func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) {
@@ -68,7 +69,7 @@ func (p *PrivKeyEd25519) UnmarshalJSON(enc []byte) error {
 }
 
 func (privKey PrivKeyEd25519) String() string {
-       return Fmt("PrivKeyEd25519{*****}")
+       return hex.EncodeToString(privKey[:])
 }
 
 func GenPrivKeyEd25519() PrivKeyEd25519 {