log.WithFields(log.Fields{"module": logModule, "err": err}).Fatal("failed to start node")
}
- nodeInfo := n.NodeInfo()
log.WithFields(log.Fields{
"module": logModule,
- "version": nodeInfo.Version,
- "network": nodeInfo.Network,
"duration": time.Since(startTime),
}).Info("start node complete")
// This should be set in viper so it can unmarshal into this struct
RootDir string `mapstructure:"home"`
- //The alias of the node
- NodeAlias string `mapstructure:"node_alias"`
-
//The ID of the network to json
ChainID string `mapstructure:"chain_id"`
DBBackend: "leveldb",
DBPath: "data",
KeysPath: "keystore",
- NodeAlias: "",
- // CipherServiceProvider: "ed25519",
}
}
fast_sync = true
db_backend = "leveldb"
api_addr = "0.0.0.0:9888"
-node_alias = ""
+moniker = ""
`
var mainNetConfigTmpl = `chain_id = "mainnet"
AddReactor(name string, reactor p2p.Reactor) p2p.Reactor
AddBannedPeer(string) error
StopPeerGracefully(string)
- NodeInfo() *p2p.NodeInfo
Start() (bool, error)
Stop() bool
IsListening() bool
return sm.sw.IsListening()
}
-func (sm *SyncManager) NodeInfo() *p2p.NodeInfo {
- return sm.sw.NodeInfo()
-}
-
func (sm *SyncManager) PeerCount() int {
if sm.config.VaultMode {
return 0
"github.com/vapor/mining/cpuminer"
"github.com/vapor/net/websocket"
"github.com/vapor/netsync"
- "github.com/vapor/p2p"
"github.com/vapor/protocol"
w "github.com/vapor/wallet"
)
n.Stop()
})
}
-
-func (n *Node) NodeInfo() *p2p.NodeInfo {
- return n.syncManager.NodeInfo()
-}
import (
"fmt"
"net"
- "strconv"
"github.com/tendermint/go-crypto"
cfg "github.com/vapor/config"
"github.com/vapor/consensus"
+ "github.com/vapor/errors"
"github.com/vapor/version"
)
const maxNodeInfoSize = 10240 // 10Kb
+var (
+ errDiffMajorVersion = errors.New("Peer is on a different major version.")
+ errDiffNetwork = errors.New("Peer is on a different network name.")
+ errDiffNetworkID = errors.New("Peer has different network ID.")
+)
+
//NodeInfo peer node info
type NodeInfo struct {
PubKey crypto.PubKeyEd25519 `json:"pub_key"`
Moniker string `json:"moniker"`
Network string `json:"network"`
//NetworkID used to isolate subnets with same network name
- NetworkID uint64 `json:"network_id"`
- RemoteAddr string `json:"remote_addr"`
- ListenAddr string `json:"listen_addr"`
- Version string `json:"version"` // major.minor.revision
+ NetworkID uint64 `json:"network_id"`
+ RemoteAddr string `json:"remote_addr"`
+ ListenAddr string `json:"listen_addr"`
+ Version string `json:"version"` // major.minor.revision
+ ServiceFlag consensus.ServiceFlag `json:"service_flag"`
// other application specific data
- //field 0: node service flags. field 1: node alias.
Other []string `json:"other"`
}
func NewNodeInfo(config *cfg.Config, pubkey crypto.PubKeyEd25519, listenAddr string, netID uint64) *NodeInfo {
- other := []string{strconv.FormatUint(uint64(consensus.DefaultServices), 10)}
- if config.NodeAlias != "" {
- other = append(other, config.NodeAlias)
- }
return &NodeInfo{
- PubKey: pubkey,
- Moniker: config.Moniker,
- Network: config.ChainID,
- NetworkID: netID,
- ListenAddr: listenAddr,
- Version: version.Version,
- Other: other,
+ PubKey: pubkey,
+ Moniker: config.Moniker,
+ Network: config.ChainID,
+ NetworkID: netID,
+ ListenAddr: listenAddr,
+ Version: version.Version,
+ ServiceFlag: consensus.DefaultServices,
}
}
+type VersionCompatibleWith func(remoteVerStr string) (bool, error)
+
// CompatibleWith checks if two NodeInfo are compatible with eachother.
// CONTRACT: two nodes are compatible if the major version matches and network match
-func (info *NodeInfo) CompatibleWith(other *NodeInfo) error {
+func (info *NodeInfo) compatibleWith(other *NodeInfo, versionCompatibleWith VersionCompatibleWith) error {
if info.Network != other.Network {
- return fmt.Errorf("Peer is on a different network. Peer network: %v, node network: %v", other.Network, info.Network)
+ return errors.Wrapf(errDiffNetwork, "Peer network: %v, node network: %v", other.Network, info.Network)
}
if info.NetworkID != other.NetworkID {
- return fmt.Errorf("Network id dismatch. Peer network id: %v, node network id: %v", other.NetworkID, info.NetworkID)
+ return errors.Wrapf(errDiffNetworkID, "Peer network id: %v, node network id: %v", other.NetworkID, info.NetworkID)
}
- compatible, err := version.CompatibleWith(other.Version)
+ compatible, err := versionCompatibleWith(other.Version)
if err != nil {
return err
}
+
if !compatible {
- return fmt.Errorf("Peer is on a different major version. Peer version: %v, node version: %v", other.Version, info.Version)
+ return errors.Wrapf(errDiffMajorVersion, "Peer version: %v, node version: %v", other.Version, info.Version)
}
return nil
}
-func (info *NodeInfo) getPubkey() crypto.PubKeyEd25519 {
- return info.PubKey
-}
-
-//ListenHost peer listener ip address
-func (info *NodeInfo) listenHost() string {
+//listenHost peer listener ip address
+func (info NodeInfo) listenHost() string {
host, _, _ := net.SplitHostPort(info.ListenAddr)
return host
}
-//RemoteAddrHost peer external ip address
-func (info *NodeInfo) remoteAddrHost() string {
+//remoteAddrHost peer external ip address
+func (info NodeInfo) remoteAddrHost() string {
host, _, _ := net.SplitHostPort(info.RemoteAddr)
return host
}
-//GetNetwork get node info network field
-func (info *NodeInfo) GetNetwork() string {
- return info.Network
-}
-
//String representation
func (info NodeInfo) String() string {
- return fmt.Sprintf("NodeInfo{pk: %v, moniker: %v, network: %v [listen %v], version: %v (%v)}", info.PubKey, info.Moniker, info.Network, info.ListenAddr, info.Version, info.Other)
+ return fmt.Sprintf("NodeInfo{pk: %v, moniker: %v, network: %v [listen %v],networkID: %x, service: %v,version: %v (%v)}", info.PubKey, info.Moniker, info.Network, info.ListenAddr, info.NetworkID, info.ServiceFlag, info.Version, info.Other)
}
--- /dev/null
+package p2p
+
+import (
+ "bytes"
+ "reflect"
+ "testing"
+
+ "github.com/davecgh/go-spew/spew"
+ "github.com/tendermint/go-crypto"
+ "github.com/tendermint/go-wire"
+
+ "github.com/vapor/errors"
+)
+
+func mockCompatibleWithFalse(remoteVerStr string) (bool, error) {
+ return false, nil
+}
+
+func mockCompatibleWithTrue(remoteVerStr string) (bool, error) {
+ return true, nil
+}
+
+func TestCompatibleWith(t *testing.T) {
+ nodeInfo := &NodeInfo{Network: "testnet", NetworkID: 0x888}
+
+ cases := []struct {
+ other *NodeInfo
+ versionCompatibleWith VersionCompatibleWith
+ err error
+ }{
+ {other: &NodeInfo{Network: "mainnet", NetworkID: 0x888}, versionCompatibleWith: mockCompatibleWithTrue, err: errDiffNetwork},
+ {other: &NodeInfo{Network: "testnet", NetworkID: 0x888}, versionCompatibleWith: mockCompatibleWithTrue, err: nil},
+ {other: &NodeInfo{Network: "testnet", NetworkID: 0x999}, versionCompatibleWith: mockCompatibleWithTrue, err: errDiffNetworkID},
+ {other: &NodeInfo{Network: "testnet", NetworkID: 0x888}, versionCompatibleWith: mockCompatibleWithFalse, err: errDiffMajorVersion},
+ }
+
+ for i, c := range cases {
+ if err := nodeInfo.compatibleWith(c.other, c.versionCompatibleWith); errors.Root(err) != c.err {
+ t.Fatalf("index:%d node info compatible test err want:%s result:%s", i, c.err, err)
+ }
+ }
+}
+
+func TestNodeInfoWriteRead(t *testing.T) {
+ nodeInfo := &NodeInfo{PubKey: crypto.GenPrivKeyEd25519().PubKey().Unwrap().(crypto.PubKeyEd25519), Moniker: "bytomd", Network: "mainnet", NetworkID: 0x888, RemoteAddr: "127.0.0.2:0", ListenAddr: "127.0.0.1:0", Version: "1.1.0-test", ServiceFlag: 10, Other: []string{"abc", "bcd"}}
+ n, err, err1 := new(int), new(error), new(error)
+ buf := new(bytes.Buffer)
+
+ wire.WriteBinary(nodeInfo, buf, n, err)
+ if *err != nil {
+ t.Fatal(*err)
+ }
+
+ peerNodeInfo := new(NodeInfo)
+ wire.ReadBinary(peerNodeInfo, buf, maxNodeInfoSize, new(int), err1)
+ if *err1 != nil {
+ t.Fatal(*err1)
+ }
+
+ if !reflect.DeepEqual(*nodeInfo, *peerNodeInfo) {
+ t.Fatal("TestNodeInfoWriteRead err", spew.Sdump(nodeInfo), spew.Sdump(peerNodeInfo))
+ }
+}
"fmt"
"net"
"reflect"
- "strconv"
"time"
"github.com/btcsuite/go-socks/socks"
return nil, errors.Wrap(err, "Error creating peer")
}
+ // Remove deadline
+ if err := rawConn.SetDeadline(time.Time{}); err != nil {
+ return nil, err
+ }
+
return &peerConn{
config: config,
outbound: outbound,
// ServiceFlag return the ServiceFlag of this peer
func (p *Peer) ServiceFlag() consensus.ServiceFlag {
- services := consensus.SFFullNode
- if len(p.Other) == 0 {
- return services
- }
-
- if serviceFlag, err := strconv.ParseUint(p.Other[0], 10, 64); err == nil {
- services = consensus.ServiceFlag(serviceFlag)
- }
- return services
+ // ServiceFlag return the ServiceFlag of this peer
+ return p.NodeInfo.ServiceFlag
}
// String representation.
sw.AddListener(l)
sw.BaseService = *cmn.NewBaseService(nil, "P2P Switch", sw)
trust.Init()
+ log.WithFields(log.Fields{"module": logModule, "nodeInfo": sw.nodeInfo}).Info("init p2p network")
return sw, nil
}
if err := version.Status.CheckUpdate(sw.nodeInfo.Version, peerNodeInfo.Version, peerNodeInfo.RemoteAddr); err != nil {
return err
}
- if err := sw.nodeInfo.CompatibleWith(peerNodeInfo); err != nil {
+
+ if err := sw.nodeInfo.compatibleWith(peerNodeInfo, version.CompatibleWith); err != nil {
return err
}
return
}
-// NodeInfo returns the switch's NodeInfo.
-// NOTE: Not goroutine safe.
-func (sw *Switch) NodeInfo() *NodeInfo {
- return sw.nodeInfo
-}
-
//Peers return switch peerset
func (sw *Switch) Peers() *PeerSet {
return sw.peers
return err
}
- if sw.nodeInfo.getPubkey().Equals(peer.PubKey().Wrap()) {
+ if sw.nodeInfo.PubKey.Equals(peer.PubKey().Wrap()) {
return ErrConnectSelf
}
var wg sync.WaitGroup
for _, address := range addresses {
- if sw.NodeInfo().ListenAddr == address.String() {
+ if sw.nodeInfo.ListenAddr == address.String() {
continue
}
if dialling := sw.IsDialing(address); dialling {