peer.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897
  1. package eth
  2. import (
  3. "bytes"
  4. "container/list"
  5. "fmt"
  6. "math"
  7. "math/big"
  8. "net"
  9. "strconv"
  10. "strings"
  11. "sync/atomic"
  12. "time"
  13. "github.com/ethereum/go-ethereum/core/types"
  14. "github.com/ethereum/go-ethereum/ethutil"
  15. "github.com/ethereum/go-ethereum/logger"
  16. "github.com/ethereum/go-ethereum/wire"
  17. )
  18. var peerlogger = logger.NewLogger("PEER")
  19. const (
  20. // The size of the output buffer for writing messages
  21. outputBufferSize = 50
  22. // Current protocol version
  23. ProtocolVersion = 46
  24. // Current P2P version
  25. P2PVersion = 2
  26. // Ethereum network version
  27. NetVersion = 0
  28. // Interval for ping/pong message
  29. pingPongTimer = 2 * time.Second
  30. )
  31. type DiscReason byte
  32. const (
  33. // Values are given explicitly instead of by iota because these values are
  34. // defined by the wire protocol spec; it is easier for humans to ensure
  35. // correctness when values are explicit.
  36. DiscRequested DiscReason = iota
  37. DiscReTcpSysErr
  38. DiscBadProto
  39. DiscBadPeer
  40. DiscTooManyPeers
  41. DiscConnDup
  42. DiscGenesisErr
  43. DiscProtoErr
  44. DiscQuitting
  45. )
  46. var discReasonToString = []string{
  47. "requested",
  48. "TCP sys error",
  49. "bad protocol",
  50. "useless peer",
  51. "too many peers",
  52. "already connected",
  53. "wrong genesis block",
  54. "incompatible network",
  55. "quitting",
  56. }
  57. func (d DiscReason) String() string {
  58. if len(discReasonToString) < int(d) {
  59. return "Unknown"
  60. }
  61. return discReasonToString[d]
  62. }
  63. // Peer capabilities
  64. type Caps byte
  65. const (
  66. CapPeerDiscTy Caps = 1 << iota
  67. CapTxTy
  68. CapChainTy
  69. CapDefault = CapChainTy | CapTxTy | CapPeerDiscTy
  70. )
  71. var capsToString = map[Caps]string{
  72. CapPeerDiscTy: "Peer discovery",
  73. CapTxTy: "Transaction relaying",
  74. CapChainTy: "Block chain relaying",
  75. }
  76. func (c Caps) IsCap(cap Caps) bool {
  77. return c&cap > 0
  78. }
  79. func (c Caps) String() string {
  80. var caps []string
  81. if c.IsCap(CapPeerDiscTy) {
  82. caps = append(caps, capsToString[CapPeerDiscTy])
  83. }
  84. if c.IsCap(CapChainTy) {
  85. caps = append(caps, capsToString[CapChainTy])
  86. }
  87. if c.IsCap(CapTxTy) {
  88. caps = append(caps, capsToString[CapTxTy])
  89. }
  90. return strings.Join(caps, " | ")
  91. }
  92. type Peer struct {
  93. // Ethereum interface
  94. ethereum *Ethereum
  95. // Net connection
  96. conn net.Conn
  97. // Output queue which is used to communicate and handle messages
  98. outputQueue chan *wire.Msg
  99. // Quit channel
  100. quit chan bool
  101. // Determines whether it's an inbound or outbound peer
  102. inbound bool
  103. // Flag for checking the peer's connectivity state
  104. connected int32
  105. disconnect int32
  106. // Last known message send
  107. lastSend time.Time
  108. // Indicated whether a verack has been send or not
  109. // This flag is used by writeMessage to check if messages are allowed
  110. // to be send or not. If no version is known all messages are ignored.
  111. versionKnown bool
  112. statusKnown bool
  113. // Last received pong message
  114. lastPong int64
  115. lastBlockReceived time.Time
  116. doneFetchingHashes bool
  117. host []byte
  118. port uint16
  119. caps Caps
  120. td *big.Int
  121. bestHash []byte
  122. lastReceivedHash []byte
  123. requestedHashes [][]byte
  124. // This peer's public key
  125. pubkey []byte
  126. // Indicated whether the node is catching up or not
  127. catchingUp bool
  128. diverted bool
  129. blocksRequested int
  130. version string
  131. // We use this to give some kind of pingtime to a node, not very accurate, could be improved.
  132. pingTime time.Duration
  133. pingStartTime time.Time
  134. lastRequestedBlock *types.Block
  135. protocolCaps *ethutil.Value
  136. }
  137. func NewPeer(conn net.Conn, ethereum *Ethereum, inbound bool) *Peer {
  138. pubkey := ethereum.KeyManager().PublicKey()[1:]
  139. return &Peer{
  140. outputQueue: make(chan *wire.Msg, outputBufferSize),
  141. quit: make(chan bool),
  142. ethereum: ethereum,
  143. conn: conn,
  144. inbound: inbound,
  145. disconnect: 0,
  146. connected: 1,
  147. port: 30303,
  148. pubkey: pubkey,
  149. blocksRequested: 10,
  150. caps: ethereum.ServerCaps(),
  151. version: ethereum.ClientIdentity().String(),
  152. protocolCaps: ethutil.NewValue(nil),
  153. td: big.NewInt(0),
  154. doneFetchingHashes: true,
  155. }
  156. }
  157. func NewOutboundPeer(addr string, ethereum *Ethereum, caps Caps) *Peer {
  158. p := &Peer{
  159. outputQueue: make(chan *wire.Msg, outputBufferSize),
  160. quit: make(chan bool),
  161. ethereum: ethereum,
  162. inbound: false,
  163. connected: 0,
  164. disconnect: 0,
  165. port: 30303,
  166. caps: caps,
  167. version: ethereum.ClientIdentity().String(),
  168. protocolCaps: ethutil.NewValue(nil),
  169. td: big.NewInt(0),
  170. doneFetchingHashes: true,
  171. }
  172. // Set up the connection in another goroutine so we don't block the main thread
  173. go func() {
  174. conn, err := p.Connect(addr)
  175. if err != nil {
  176. //peerlogger.Debugln("Connection to peer failed. Giving up.", err)
  177. p.Stop()
  178. return
  179. }
  180. p.conn = conn
  181. // Atomically set the connection state
  182. atomic.StoreInt32(&p.connected, 1)
  183. atomic.StoreInt32(&p.disconnect, 0)
  184. p.Start()
  185. }()
  186. return p
  187. }
  188. func (self *Peer) Connect(addr string) (conn net.Conn, err error) {
  189. const maxTries = 3
  190. for attempts := 0; attempts < maxTries; attempts++ {
  191. conn, err = net.DialTimeout("tcp", addr, 10*time.Second)
  192. if err != nil {
  193. time.Sleep(time.Duration(attempts*20) * time.Second)
  194. continue
  195. }
  196. // Success
  197. return
  198. }
  199. return
  200. }
  201. // Getters
  202. func (p *Peer) PingTime() string {
  203. return p.pingTime.String()
  204. }
  205. func (p *Peer) Inbound() bool {
  206. return p.inbound
  207. }
  208. func (p *Peer) LastSend() time.Time {
  209. return p.lastSend
  210. }
  211. func (p *Peer) LastPong() int64 {
  212. return p.lastPong
  213. }
  214. func (p *Peer) Host() []byte {
  215. return p.host
  216. }
  217. func (p *Peer) Port() uint16 {
  218. return p.port
  219. }
  220. func (p *Peer) Version() string {
  221. return p.version
  222. }
  223. func (p *Peer) Connected() *int32 {
  224. return &p.connected
  225. }
  226. // Setters
  227. func (p *Peer) SetVersion(version string) {
  228. p.version = version
  229. }
  230. // Outputs any RLP encoded data to the peer
  231. func (p *Peer) QueueMessage(msg *wire.Msg) {
  232. if atomic.LoadInt32(&p.connected) != 1 {
  233. return
  234. }
  235. p.outputQueue <- msg
  236. }
  237. func (p *Peer) writeMessage(msg *wire.Msg) {
  238. // Ignore the write if we're not connected
  239. if atomic.LoadInt32(&p.connected) != 1 {
  240. return
  241. }
  242. if !p.versionKnown {
  243. switch msg.Type {
  244. case wire.MsgHandshakeTy: // Ok
  245. default: // Anything but ack is allowed
  246. return
  247. }
  248. } else {
  249. /*
  250. if !p.statusKnown {
  251. switch msg.Type {
  252. case wire.MsgStatusTy: // Ok
  253. default: // Anything but ack is allowed
  254. return
  255. }
  256. }
  257. */
  258. }
  259. peerlogger.DebugDetailf("(%v) <= %v\n", p.conn.RemoteAddr(), formatMessage(msg))
  260. err := wire.WriteMessage(p.conn, msg)
  261. if err != nil {
  262. peerlogger.Debugln(" Can't send message:", err)
  263. // Stop the client if there was an error writing to it
  264. p.Stop()
  265. return
  266. }
  267. }
  268. // Outbound message handler. Outbound messages are handled here
  269. func (p *Peer) HandleOutbound() {
  270. // The ping timer. Makes sure that every 2 minutes a ping is send to the peer
  271. pingTimer := time.NewTicker(pingPongTimer)
  272. serviceTimer := time.NewTicker(10 * time.Second)
  273. out:
  274. for {
  275. skip:
  276. select {
  277. // Main message queue. All outbound messages are processed through here
  278. case msg := <-p.outputQueue:
  279. if !p.statusKnown {
  280. switch msg.Type {
  281. case wire.MsgTxTy, wire.MsgGetBlockHashesTy, wire.MsgBlockHashesTy, wire.MsgGetBlocksTy, wire.MsgBlockTy:
  282. break skip
  283. }
  284. }
  285. p.writeMessage(msg)
  286. p.lastSend = time.Now()
  287. // Ping timer
  288. case <-pingTimer.C:
  289. /*
  290. timeSince := time.Since(time.Unix(p.lastPong, 0))
  291. if !p.pingStartTime.IsZero() && p.lastPong != 0 && timeSince > (pingPongTimer+30*time.Second) {
  292. peerlogger.Infof("Peer did not respond to latest pong fast enough, it took %s, disconnecting.\n", timeSince)
  293. p.Stop()
  294. return
  295. }
  296. */
  297. p.writeMessage(wire.NewMessage(wire.MsgPingTy, ""))
  298. p.pingStartTime = time.Now()
  299. // Service timer takes care of peer broadcasting, transaction
  300. // posting or block posting
  301. case <-serviceTimer.C:
  302. p.QueueMessage(wire.NewMessage(wire.MsgGetPeersTy, ""))
  303. case <-p.quit:
  304. // Break out of the for loop if a quit message is posted
  305. break out
  306. }
  307. }
  308. clean:
  309. // This loop is for draining the output queue and anybody waiting for us
  310. for {
  311. select {
  312. case <-p.outputQueue:
  313. // TODO
  314. default:
  315. break clean
  316. }
  317. }
  318. }
  319. func formatMessage(msg *wire.Msg) (ret string) {
  320. ret = fmt.Sprintf("%v %v", msg.Type, msg.Data)
  321. /*
  322. XXX Commented out because I need the log level here to determine
  323. if i should or shouldn't generate this message
  324. */
  325. /*
  326. switch msg.Type {
  327. case wire.MsgPeersTy:
  328. ret += fmt.Sprintf("(%d entries)", msg.Data.Len())
  329. case wire.MsgBlockTy:
  330. b1, b2 := chain.NewBlockFromRlpValue(msg.Data.Get(0)), ethchain.NewBlockFromRlpValue(msg.Data.Get(msg.Data.Len()-1))
  331. ret += fmt.Sprintf("(%d entries) %x - %x", msg.Data.Len(), b1.Hash()[0:4], b2.Hash()[0:4])
  332. case wire.MsgBlockHashesTy:
  333. h1, h2 := msg.Data.Get(0).Bytes(), msg.Data.Get(msg.Data.Len()-1).Bytes()
  334. ret += fmt.Sprintf("(%d entries) %x - %x", msg.Data.Len(), h1, h2)
  335. }
  336. */
  337. return
  338. }
  339. // Inbound handler. Inbound messages are received here and passed to the appropriate methods
  340. func (p *Peer) HandleInbound() {
  341. for atomic.LoadInt32(&p.disconnect) == 0 {
  342. // HMM?
  343. time.Sleep(50 * time.Millisecond)
  344. // Wait for a message from the peer
  345. msgs, err := wire.ReadMessages(p.conn)
  346. if err != nil {
  347. peerlogger.Debugln(err)
  348. }
  349. for _, msg := range msgs {
  350. peerlogger.DebugDetailf("(%v) => %v\n", p.conn.RemoteAddr(), formatMessage(msg))
  351. switch msg.Type {
  352. case wire.MsgHandshakeTy:
  353. // Version message
  354. p.handleHandshake(msg)
  355. //if p.caps.IsCap(CapPeerDiscTy) {
  356. p.QueueMessage(wire.NewMessage(wire.MsgGetPeersTy, ""))
  357. //}
  358. case wire.MsgDiscTy:
  359. p.Stop()
  360. peerlogger.Infoln("Disconnect peer: ", DiscReason(msg.Data.Get(0).Uint()))
  361. case wire.MsgPingTy:
  362. // Respond back with pong
  363. p.QueueMessage(wire.NewMessage(wire.MsgPongTy, ""))
  364. case wire.MsgPongTy:
  365. // If we received a pong back from a peer we set the
  366. // last pong so the peer handler knows this peer is still
  367. // active.
  368. p.lastPong = time.Now().Unix()
  369. p.pingTime = time.Since(p.pingStartTime)
  370. case wire.MsgTxTy:
  371. // If the message was a transaction queue the transaction
  372. // in the TxPool where it will undergo validation and
  373. // processing when a new block is found
  374. for i := 0; i < msg.Data.Len(); i++ {
  375. tx := types.NewTransactionFromValue(msg.Data.Get(i))
  376. err := p.ethereum.TxPool().Add(tx)
  377. if err != nil {
  378. peerlogger.Infoln(err)
  379. } else {
  380. peerlogger.Infof("tx OK (%x)\n", tx.Hash()[0:4])
  381. }
  382. }
  383. case wire.MsgGetPeersTy:
  384. // Peer asked for list of connected peers
  385. //p.pushPeers()
  386. case wire.MsgPeersTy:
  387. // Received a list of peers (probably because MsgGetPeersTy was send)
  388. data := msg.Data
  389. // Create new list of possible peers for the ethereum to process
  390. peers := make([]string, data.Len())
  391. // Parse each possible peer
  392. for i := 0; i < data.Len(); i++ {
  393. value := data.Get(i)
  394. peers[i] = unpackAddr(value.Get(0), value.Get(1).Uint())
  395. }
  396. // Connect to the list of peers
  397. p.ethereum.ProcessPeerList(peers)
  398. case wire.MsgStatusTy:
  399. // Handle peer's status msg
  400. p.handleStatus(msg)
  401. }
  402. // TMP
  403. if p.statusKnown {
  404. switch msg.Type {
  405. /*
  406. case wire.MsgGetTxsTy:
  407. // Get the current transactions of the pool
  408. txs := p.ethereum.TxPool().CurrentTransactions()
  409. // Get the RlpData values from the txs
  410. txsInterface := make([]interface{}, len(txs))
  411. for i, tx := range txs {
  412. txsInterface[i] = tx.RlpData()
  413. }
  414. // Broadcast it back to the peer
  415. p.QueueMessage(wire.NewMessage(wire.MsgTxTy, txsInterface))
  416. */
  417. case wire.MsgGetBlockHashesTy:
  418. if msg.Data.Len() < 2 {
  419. peerlogger.Debugln("err: argument length invalid ", msg.Data.Len())
  420. }
  421. hash := msg.Data.Get(0).Bytes()
  422. amount := msg.Data.Get(1).Uint()
  423. hashes := p.ethereum.ChainManager().GetChainHashesFromHash(hash, amount)
  424. p.QueueMessage(wire.NewMessage(wire.MsgBlockHashesTy, ethutil.ByteSliceToInterface(hashes)))
  425. case wire.MsgGetBlocksTy:
  426. // Limit to max 300 blocks
  427. max := int(math.Min(float64(msg.Data.Len()), 300.0))
  428. var blocks []interface{}
  429. for i := 0; i < max; i++ {
  430. hash := msg.Data.Get(i).Bytes()
  431. block := p.ethereum.ChainManager().GetBlock(hash)
  432. if block != nil {
  433. blocks = append(blocks, block.Value().Raw())
  434. }
  435. }
  436. p.QueueMessage(wire.NewMessage(wire.MsgBlockTy, blocks))
  437. case wire.MsgBlockHashesTy:
  438. p.catchingUp = true
  439. blockPool := p.ethereum.blockPool
  440. foundCommonHash := false
  441. it := msg.Data.NewIterator()
  442. for it.Next() {
  443. hash := it.Value().Bytes()
  444. p.lastReceivedHash = hash
  445. if blockPool.HasCommonHash(hash) {
  446. foundCommonHash = true
  447. break
  448. }
  449. blockPool.AddHash(hash, p)
  450. }
  451. if !foundCommonHash {
  452. //if !p.FetchHashes() {
  453. // p.doneFetchingHashes = true
  454. //}
  455. p.FetchHashes()
  456. } else {
  457. peerlogger.Infof("Found common hash (%x...)\n", p.lastReceivedHash[0:4])
  458. p.doneFetchingHashes = true
  459. }
  460. case wire.MsgBlockTy:
  461. p.catchingUp = true
  462. blockPool := p.ethereum.blockPool
  463. it := msg.Data.NewIterator()
  464. for it.Next() {
  465. block := types.NewBlockFromRlpValue(it.Value())
  466. blockPool.Add(block, p)
  467. p.lastBlockReceived = time.Now()
  468. }
  469. case wire.MsgNewBlockTy:
  470. var (
  471. blockPool = p.ethereum.blockPool
  472. block = types.NewBlockFromRlpValue(msg.Data.Get(0))
  473. td = msg.Data.Get(1).BigInt()
  474. )
  475. if td.Cmp(blockPool.td) > 0 {
  476. p.ethereum.blockPool.AddNew(block, p)
  477. }
  478. }
  479. }
  480. }
  481. }
  482. p.Stop()
  483. }
  484. func (self *Peer) FetchBlocks(hashes [][]byte) {
  485. if len(hashes) > 0 {
  486. peerlogger.Debugf("Fetching blocks (%d)\n", len(hashes))
  487. self.QueueMessage(wire.NewMessage(wire.MsgGetBlocksTy, ethutil.ByteSliceToInterface(hashes)))
  488. }
  489. }
  490. func (self *Peer) FetchHashes() bool {
  491. blockPool := self.ethereum.blockPool
  492. return blockPool.FetchHashes(self)
  493. }
  494. func (self *Peer) FetchingHashes() bool {
  495. return !self.doneFetchingHashes
  496. }
  497. // General update method
  498. func (self *Peer) update() {
  499. serviceTimer := time.NewTicker(100 * time.Millisecond)
  500. out:
  501. for {
  502. select {
  503. case <-serviceTimer.C:
  504. if self.IsCap("eth") {
  505. var (
  506. sinceBlock = time.Since(self.lastBlockReceived)
  507. )
  508. if sinceBlock > 5*time.Second {
  509. self.catchingUp = false
  510. }
  511. }
  512. case <-self.quit:
  513. break out
  514. }
  515. }
  516. serviceTimer.Stop()
  517. }
  518. func (p *Peer) Start() {
  519. peerHost, peerPort, _ := net.SplitHostPort(p.conn.LocalAddr().String())
  520. servHost, servPort, _ := net.SplitHostPort(p.conn.RemoteAddr().String())
  521. if p.inbound {
  522. p.host, p.port = packAddr(peerHost, peerPort)
  523. } else {
  524. p.host, p.port = packAddr(servHost, servPort)
  525. }
  526. err := p.pushHandshake()
  527. if err != nil {
  528. peerlogger.Debugln("Peer can't send outbound version ack", err)
  529. p.Stop()
  530. return
  531. }
  532. go p.HandleOutbound()
  533. // Run the inbound handler in a new goroutine
  534. go p.HandleInbound()
  535. // Run the general update handler
  536. go p.update()
  537. // Wait a few seconds for startup and then ask for an initial ping
  538. time.Sleep(2 * time.Second)
  539. p.writeMessage(wire.NewMessage(wire.MsgPingTy, ""))
  540. p.pingStartTime = time.Now()
  541. }
  542. func (p *Peer) Stop() {
  543. p.StopWithReason(DiscRequested)
  544. }
  545. func (p *Peer) StopWithReason(reason DiscReason) {
  546. if atomic.AddInt32(&p.disconnect, 1) != 1 {
  547. return
  548. }
  549. // Pre-emptively remove the peer; don't wait for reaping. We already know it's dead if we are here
  550. p.ethereum.RemovePeer(p)
  551. close(p.quit)
  552. if atomic.LoadInt32(&p.connected) != 0 {
  553. p.writeMessage(wire.NewMessage(wire.MsgDiscTy, reason))
  554. p.conn.Close()
  555. }
  556. }
  557. func (p *Peer) peersMessage() *wire.Msg {
  558. outPeers := make([]interface{}, len(p.ethereum.InOutPeers()))
  559. // Serialise each peer
  560. for i, peer := range p.ethereum.InOutPeers() {
  561. // Don't return localhost as valid peer
  562. if !net.ParseIP(peer.conn.RemoteAddr().String()).IsLoopback() {
  563. outPeers[i] = peer.RlpData()
  564. }
  565. }
  566. // Return the message to the peer with the known list of connected clients
  567. return wire.NewMessage(wire.MsgPeersTy, outPeers)
  568. }
  569. // Pushes the list of outbound peers to the client when requested
  570. func (p *Peer) pushPeers() {
  571. p.QueueMessage(p.peersMessage())
  572. }
  573. func (self *Peer) pushStatus() {
  574. msg := wire.NewMessage(wire.MsgStatusTy, []interface{}{
  575. uint32(ProtocolVersion),
  576. uint32(NetVersion),
  577. self.ethereum.ChainManager().TD,
  578. self.ethereum.ChainManager().CurrentBlock.Hash(),
  579. self.ethereum.ChainManager().Genesis().Hash(),
  580. })
  581. self.QueueMessage(msg)
  582. }
  583. func (self *Peer) handleStatus(msg *wire.Msg) {
  584. c := msg.Data
  585. var (
  586. //protoVersion = c.Get(0).Uint()
  587. netVersion = c.Get(1).Uint()
  588. td = c.Get(2).BigInt()
  589. bestHash = c.Get(3).Bytes()
  590. genesis = c.Get(4).Bytes()
  591. )
  592. if bytes.Compare(self.ethereum.ChainManager().Genesis().Hash(), genesis) != 0 {
  593. loggerger.Warnf("Invalid genisis hash %x. Disabling [eth]\n", genesis)
  594. return
  595. }
  596. if netVersion != NetVersion {
  597. loggerger.Warnf("Invalid network version %d. Disabling [eth]\n", netVersion)
  598. return
  599. }
  600. /*
  601. if protoVersion != ProtocolVersion {
  602. loggerger.Warnf("Invalid protocol version %d. Disabling [eth]\n", protoVersion)
  603. return
  604. }
  605. */
  606. // Get the td and last hash
  607. self.td = td
  608. self.bestHash = bestHash
  609. self.lastReceivedHash = bestHash
  610. self.statusKnown = true
  611. // Compare the total TD with the blockchain TD. If remote is higher
  612. // fetch hashes from highest TD node.
  613. self.FetchHashes()
  614. loggerger.Infof("Peer is [eth] capable. (TD = %v ~ %x)", self.td, self.bestHash)
  615. }
  616. func (p *Peer) pushHandshake() error {
  617. pubkey := p.ethereum.KeyManager().PublicKey()
  618. msg := wire.NewMessage(wire.MsgHandshakeTy, []interface{}{
  619. P2PVersion, []byte(p.version), []interface{}{[]interface{}{"eth", ProtocolVersion}}, p.port, pubkey[1:],
  620. })
  621. p.QueueMessage(msg)
  622. return nil
  623. }
  624. func (p *Peer) handleHandshake(msg *wire.Msg) {
  625. c := msg.Data
  626. var (
  627. p2pVersion = c.Get(0).Uint()
  628. clientId = c.Get(1).Str()
  629. caps = c.Get(2)
  630. port = c.Get(3).Uint()
  631. pub = c.Get(4).Bytes()
  632. )
  633. // Check correctness of p2p protocol version
  634. if p2pVersion != P2PVersion {
  635. fmt.Println(p)
  636. peerlogger.Debugf("Invalid P2P version. Require protocol %d, received %d\n", P2PVersion, p2pVersion)
  637. p.Stop()
  638. return
  639. }
  640. // Handle the pub key (validation, uniqueness)
  641. if len(pub) == 0 {
  642. peerlogger.Warnln("Pubkey required, not supplied in handshake.")
  643. p.Stop()
  644. return
  645. }
  646. // Self connect detection
  647. pubkey := p.ethereum.KeyManager().PublicKey()
  648. if bytes.Compare(pubkey[1:], pub) == 0 {
  649. p.Stop()
  650. return
  651. }
  652. // Check for blacklisting
  653. for _, pk := range p.ethereum.blacklist {
  654. if bytes.Compare(pk, pub) == 0 {
  655. peerlogger.Debugf("Blacklisted peer tried to connect (%x...)\n", pubkey[0:4])
  656. p.StopWithReason(DiscBadPeer)
  657. return
  658. }
  659. }
  660. usedPub := 0
  661. // This peer is already added to the peerlist so we expect to find a double pubkey at least once
  662. eachPeer(p.ethereum.Peers(), func(peer *Peer, e *list.Element) {
  663. if bytes.Compare(pub, peer.pubkey) == 0 {
  664. usedPub++
  665. }
  666. })
  667. if usedPub > 0 {
  668. peerlogger.Debugf("Pubkey %x found more then once. Already connected to client.", p.pubkey)
  669. p.Stop()
  670. return
  671. }
  672. p.pubkey = pub
  673. // If this is an inbound connection send an ack back
  674. if p.inbound {
  675. p.port = uint16(port)
  676. }
  677. p.SetVersion(clientId)
  678. p.versionKnown = true
  679. p.ethereum.PushPeer(p)
  680. p.ethereum.eventMux.Post(PeerListEvent{p.ethereum.Peers()})
  681. p.protocolCaps = caps
  682. it := caps.NewIterator()
  683. var capsStrs []string
  684. for it.Next() {
  685. cap := it.Value().Get(0).Str()
  686. ver := it.Value().Get(1).Uint()
  687. switch cap {
  688. case "eth":
  689. if ver != ProtocolVersion {
  690. loggerger.Warnf("Invalid protocol version %d. Disabling [eth]\n", ver)
  691. continue
  692. }
  693. p.pushStatus()
  694. }
  695. capsStrs = append(capsStrs, fmt.Sprintf("%s/%d", cap, ver))
  696. }
  697. peerlogger.Infof("Added peer (%s) %d / %d (%v)\n", p.conn.RemoteAddr(), p.ethereum.Peers().Len(), p.ethereum.MaxPeers, capsStrs)
  698. peerlogger.Debugln(p)
  699. }
  700. func (self *Peer) IsCap(cap string) bool {
  701. capsIt := self.protocolCaps.NewIterator()
  702. for capsIt.Next() {
  703. if capsIt.Value().Str() == cap {
  704. return true
  705. }
  706. }
  707. return false
  708. }
  709. func (self *Peer) Caps() *ethutil.Value {
  710. return self.protocolCaps
  711. }
  712. func (p *Peer) String() string {
  713. var strBoundType string
  714. if p.inbound {
  715. strBoundType = "inbound"
  716. } else {
  717. strBoundType = "outbound"
  718. }
  719. var strConnectType string
  720. if atomic.LoadInt32(&p.disconnect) == 0 {
  721. strConnectType = "connected"
  722. } else {
  723. strConnectType = "disconnected"
  724. }
  725. return fmt.Sprintf("[%s] (%s) %v %s", strConnectType, strBoundType, p.conn.RemoteAddr(), p.version)
  726. }
  727. func (p *Peer) RlpData() []interface{} {
  728. return []interface{}{p.host, p.port, p.pubkey}
  729. }
  730. func packAddr(address, _port string) (host []byte, port uint16) {
  731. p, _ := strconv.Atoi(_port)
  732. port = uint16(p)
  733. h := net.ParseIP(address)
  734. if ip := h.To4(); ip != nil {
  735. host = []byte(ip)
  736. } else {
  737. host = []byte(h)
  738. }
  739. return
  740. }
  741. func unpackAddr(value *ethutil.Value, p uint64) string {
  742. host, _ := net.IP(value.Bytes()).MarshalText()
  743. prt := strconv.Itoa(int(p))
  744. return net.JoinHostPort(string(host), prt)
  745. }