github.com/lbryio/lbcd@v0.22.119/peer/peer_test.go (about) 1 // Copyright (c) 2015-2016 The btcsuite developers 2 // Copyright (c) 2016-2018 The Decred developers 3 // Use of this source code is governed by an ISC 4 // license that can be found in the LICENSE file. 5 6 package peer_test 7 8 import ( 9 "errors" 10 "io" 11 "net" 12 "strconv" 13 "testing" 14 "time" 15 16 "github.com/btcsuite/go-socks/socks" 17 "github.com/lbryio/lbcd/chaincfg" 18 "github.com/lbryio/lbcd/chaincfg/chainhash" 19 "github.com/lbryio/lbcd/peer" 20 "github.com/lbryio/lbcd/wire" 21 ) 22 23 // conn mocks a network connection by implementing the net.Conn interface. It 24 // is used to test peer connection without actually opening a network 25 // connection. 26 type conn struct { 27 io.Reader 28 io.Writer 29 io.Closer 30 31 // local network, address for the connection. 32 lnet, laddr string 33 34 // remote network, address for the connection. 35 rnet, raddr string 36 37 // mocks socks proxy if true 38 proxy bool 39 } 40 41 // LocalAddr returns the local address for the connection. 42 func (c conn) LocalAddr() net.Addr { 43 return &addr{c.lnet, c.laddr} 44 } 45 46 // Remote returns the remote address for the connection. 47 func (c conn) RemoteAddr() net.Addr { 48 if !c.proxy { 49 return &addr{c.rnet, c.raddr} 50 } 51 host, strPort, _ := net.SplitHostPort(c.raddr) 52 port, _ := strconv.Atoi(strPort) 53 return &socks.ProxiedAddr{ 54 Net: c.rnet, 55 Host: host, 56 Port: port, 57 } 58 } 59 60 // Close handles closing the connection. 61 func (c conn) Close() error { 62 if c.Closer == nil { 63 return nil 64 } 65 return c.Closer.Close() 66 } 67 68 func (c conn) SetDeadline(t time.Time) error { return nil } 69 func (c conn) SetReadDeadline(t time.Time) error { return nil } 70 func (c conn) SetWriteDeadline(t time.Time) error { return nil } 71 72 // addr mocks a network address 73 type addr struct { 74 net, address string 75 } 76 77 func (m addr) Network() string { return m.net } 78 func (m addr) String() string { return m.address } 79 80 // pipe turns two mock connections into a full-duplex connection similar to 81 // net.Pipe to allow pipe's with (fake) addresses. 82 func pipe(c1, c2 *conn) (*conn, *conn) { 83 r1, w1 := io.Pipe() 84 r2, w2 := io.Pipe() 85 86 c1.Writer = w1 87 c1.Closer = w1 88 c2.Reader = r1 89 c1.Reader = r2 90 c2.Writer = w2 91 c2.Closer = w2 92 93 return c1, c2 94 } 95 96 // peerStats holds the expected peer stats used for testing peer. 97 type peerStats struct { 98 wantUserAgent string 99 wantServices wire.ServiceFlag 100 wantProtocolVersion uint32 101 wantConnected bool 102 wantVersionKnown bool 103 wantVerAckReceived bool 104 wantLastBlock int32 105 wantStartingHeight int32 106 wantLastPingTime time.Time 107 wantLastPingNonce uint64 108 wantLastPingMicros int64 109 wantTimeOffset int64 110 wantBytesSent uint64 111 wantBytesReceived uint64 112 wantWitnessEnabled bool 113 } 114 115 // testPeer tests the given peer's flags and stats 116 func testPeer(t *testing.T, p *peer.Peer, s peerStats) { 117 if p.UserAgent() != s.wantUserAgent { 118 t.Errorf("testPeer: wrong UserAgent - got %v, want %v", p.UserAgent(), s.wantUserAgent) 119 return 120 } 121 122 if p.Services() != s.wantServices { 123 t.Errorf("testPeer: wrong Services - got %v, want %v", p.Services(), s.wantServices) 124 return 125 } 126 127 if !p.LastPingTime().Equal(s.wantLastPingTime) { 128 t.Errorf("testPeer: wrong LastPingTime - got %v, want %v", p.LastPingTime(), s.wantLastPingTime) 129 return 130 } 131 132 if p.LastPingNonce() != s.wantLastPingNonce { 133 t.Errorf("testPeer: wrong LastPingNonce - got %v, want %v", p.LastPingNonce(), s.wantLastPingNonce) 134 return 135 } 136 137 if p.LastPingMicros() != s.wantLastPingMicros { 138 t.Errorf("testPeer: wrong LastPingMicros - got %v, want %v", p.LastPingMicros(), s.wantLastPingMicros) 139 return 140 } 141 142 if p.VerAckReceived() != s.wantVerAckReceived { 143 t.Errorf("testPeer: wrong VerAckReceived - got %v, want %v", p.VerAckReceived(), s.wantVerAckReceived) 144 return 145 } 146 147 if p.VersionKnown() != s.wantVersionKnown { 148 t.Errorf("testPeer: wrong VersionKnown - got %v, want %v", p.VersionKnown(), s.wantVersionKnown) 149 return 150 } 151 152 if p.ProtocolVersion() != s.wantProtocolVersion { 153 t.Errorf("testPeer: wrong ProtocolVersion - got %v, want %v", p.ProtocolVersion(), s.wantProtocolVersion) 154 return 155 } 156 157 if p.LastBlock() != s.wantLastBlock { 158 t.Errorf("testPeer: wrong LastBlock - got %v, want %v", p.LastBlock(), s.wantLastBlock) 159 return 160 } 161 162 // Allow for a deviation of 1s, as the second may tick when the message is 163 // in transit and the protocol doesn't support any further precision. 164 if p.TimeOffset() != s.wantTimeOffset && p.TimeOffset() != s.wantTimeOffset-1 { 165 t.Errorf("testPeer: wrong TimeOffset - got %v, want %v or %v", p.TimeOffset(), 166 s.wantTimeOffset, s.wantTimeOffset-1) 167 return 168 } 169 170 if p.BytesSent() != s.wantBytesSent { 171 t.Errorf("testPeer: wrong BytesSent - got %v, want %v", p.BytesSent(), s.wantBytesSent) 172 return 173 } 174 175 if p.BytesReceived() != s.wantBytesReceived { 176 t.Errorf("testPeer: wrong BytesReceived - got %v, want %v", p.BytesReceived(), s.wantBytesReceived) 177 return 178 } 179 180 if p.StartingHeight() != s.wantStartingHeight { 181 t.Errorf("testPeer: wrong StartingHeight - got %v, want %v", p.StartingHeight(), s.wantStartingHeight) 182 return 183 } 184 185 if p.Connected() != s.wantConnected { 186 t.Errorf("testPeer: wrong Connected - got %v, want %v", p.Connected(), s.wantConnected) 187 return 188 } 189 190 if p.IsWitnessEnabled() != s.wantWitnessEnabled { 191 t.Errorf("testPeer: wrong WitnessEnabled - got %v, want %v", 192 p.IsWitnessEnabled(), s.wantWitnessEnabled) 193 return 194 } 195 196 stats := p.StatsSnapshot() 197 198 if p.ID() != stats.ID { 199 t.Errorf("testPeer: wrong ID - got %v, want %v", p.ID(), stats.ID) 200 return 201 } 202 203 if p.Addr() != stats.Addr { 204 t.Errorf("testPeer: wrong Addr - got %v, want %v", p.Addr(), stats.Addr) 205 return 206 } 207 208 if p.LastSend() != stats.LastSend { 209 t.Errorf("testPeer: wrong LastSend - got %v, want %v", p.LastSend(), stats.LastSend) 210 return 211 } 212 213 if p.LastRecv() != stats.LastRecv { 214 t.Errorf("testPeer: wrong LastRecv - got %v, want %v", p.LastRecv(), stats.LastRecv) 215 return 216 } 217 } 218 219 // TestPeerConnection tests connection between inbound and outbound peers. 220 func TestPeerConnection(t *testing.T) { 221 verack := make(chan struct{}) 222 peer1Cfg := &peer.Config{ 223 Listeners: peer.MessageListeners{ 224 OnVerAck: func(p *peer.Peer, msg *wire.MsgVerAck) { 225 verack <- struct{}{} 226 }, 227 OnWrite: func(p *peer.Peer, bytesWritten int, msg wire.Message, 228 err error) { 229 if _, ok := msg.(*wire.MsgVerAck); ok { 230 verack <- struct{}{} 231 } 232 }, 233 }, 234 UserAgentName: "peer", 235 UserAgentVersion: "1.0", 236 UserAgentComments: []string{"comment"}, 237 ChainParams: &chaincfg.MainNetParams, 238 ProtocolVersion: wire.RejectVersion, // Configure with older version 239 Services: 0, 240 TrickleInterval: time.Second * 10, 241 AllowSelfConns: true, 242 } 243 peer2Cfg := &peer.Config{ 244 Listeners: peer1Cfg.Listeners, 245 UserAgentName: "peer", 246 UserAgentVersion: "1.0", 247 UserAgentComments: []string{"comment"}, 248 ChainParams: &chaincfg.MainNetParams, 249 Services: wire.SFNodeNetwork | wire.SFNodeWitness, 250 TrickleInterval: time.Second * 10, 251 AllowSelfConns: true, 252 } 253 254 wantStats1 := peerStats{ 255 wantUserAgent: wire.DefaultUserAgent + "peer:1.0(comment)/", 256 wantServices: 0, 257 wantProtocolVersion: wire.RejectVersion, 258 wantConnected: true, 259 wantVersionKnown: true, 260 wantVerAckReceived: true, 261 wantLastPingTime: time.Time{}, 262 wantLastPingNonce: uint64(0), 263 wantLastPingMicros: int64(0), 264 wantTimeOffset: int64(0), 265 wantBytesSent: 167, // 143 version + 24 verack 266 wantBytesReceived: 167, 267 wantWitnessEnabled: false, 268 } 269 wantStats2 := peerStats{ 270 wantUserAgent: wire.DefaultUserAgent + "peer:1.0(comment)/", 271 wantServices: wire.SFNodeNetwork | wire.SFNodeWitness, 272 wantProtocolVersion: wire.RejectVersion, 273 wantConnected: true, 274 wantVersionKnown: true, 275 wantVerAckReceived: true, 276 wantLastPingTime: time.Time{}, 277 wantLastPingNonce: uint64(0), 278 wantLastPingMicros: int64(0), 279 wantTimeOffset: int64(0), 280 wantBytesSent: 167, // 143 version + 24 verack 281 wantBytesReceived: 167, 282 wantWitnessEnabled: true, 283 } 284 285 tests := []struct { 286 name string 287 setup func() (*peer.Peer, *peer.Peer, error) 288 }{ 289 { 290 "basic handshake", 291 func() (*peer.Peer, *peer.Peer, error) { 292 inConn, outConn := pipe( 293 &conn{raddr: "10.0.0.1:9246"}, 294 &conn{raddr: "10.0.0.2:9246"}, 295 ) 296 inPeer := peer.NewInboundPeer(peer1Cfg) 297 inPeer.AssociateConnection(inConn) 298 299 outPeer, err := peer.NewOutboundPeer(peer2Cfg, "10.0.0.2:9246") 300 if err != nil { 301 return nil, nil, err 302 } 303 outPeer.AssociateConnection(outConn) 304 305 for i := 0; i < 4; i++ { 306 select { 307 case <-verack: 308 case <-time.After(time.Second): 309 return nil, nil, errors.New("verack timeout") 310 } 311 } 312 return inPeer, outPeer, nil 313 }, 314 }, 315 { 316 "socks proxy", 317 func() (*peer.Peer, *peer.Peer, error) { 318 inConn, outConn := pipe( 319 &conn{raddr: "10.0.0.1:9246", proxy: true}, 320 &conn{raddr: "10.0.0.2:9246"}, 321 ) 322 inPeer := peer.NewInboundPeer(peer1Cfg) 323 inPeer.AssociateConnection(inConn) 324 325 outPeer, err := peer.NewOutboundPeer(peer2Cfg, "10.0.0.2:9246") 326 if err != nil { 327 return nil, nil, err 328 } 329 outPeer.AssociateConnection(outConn) 330 331 for i := 0; i < 4; i++ { 332 select { 333 case <-verack: 334 case <-time.After(time.Second): 335 return nil, nil, errors.New("verack timeout") 336 } 337 } 338 return inPeer, outPeer, nil 339 }, 340 }, 341 } 342 t.Logf("Running %d tests", len(tests)) 343 for i, test := range tests { 344 inPeer, outPeer, err := test.setup() 345 if err != nil { 346 t.Errorf("TestPeerConnection setup #%d: unexpected err %v", i, err) 347 return 348 } 349 testPeer(t, inPeer, wantStats2) 350 testPeer(t, outPeer, wantStats1) 351 352 inPeer.Disconnect() 353 outPeer.Disconnect() 354 inPeer.WaitForDisconnect() 355 outPeer.WaitForDisconnect() 356 } 357 } 358 359 // TestPeerListeners tests that the peer listeners are called as expected. 360 func TestPeerListeners(t *testing.T) { 361 verack := make(chan struct{}, 1) 362 ok := make(chan wire.Message, 20) 363 peerCfg := &peer.Config{ 364 Listeners: peer.MessageListeners{ 365 OnGetAddr: func(p *peer.Peer, msg *wire.MsgGetAddr) { 366 ok <- msg 367 }, 368 OnAddr: func(p *peer.Peer, msg *wire.MsgAddr) { 369 ok <- msg 370 }, 371 OnPing: func(p *peer.Peer, msg *wire.MsgPing) { 372 ok <- msg 373 }, 374 OnPong: func(p *peer.Peer, msg *wire.MsgPong) { 375 ok <- msg 376 }, 377 OnAlert: func(p *peer.Peer, msg *wire.MsgAlert) { 378 ok <- msg 379 }, 380 OnMemPool: func(p *peer.Peer, msg *wire.MsgMemPool) { 381 ok <- msg 382 }, 383 OnTx: func(p *peer.Peer, msg *wire.MsgTx) { 384 ok <- msg 385 }, 386 OnBlock: func(p *peer.Peer, msg *wire.MsgBlock, buf []byte) { 387 ok <- msg 388 }, 389 OnInv: func(p *peer.Peer, msg *wire.MsgInv) { 390 ok <- msg 391 }, 392 OnHeaders: func(p *peer.Peer, msg *wire.MsgHeaders) { 393 ok <- msg 394 }, 395 OnNotFound: func(p *peer.Peer, msg *wire.MsgNotFound) { 396 ok <- msg 397 }, 398 OnGetData: func(p *peer.Peer, msg *wire.MsgGetData) { 399 ok <- msg 400 }, 401 OnGetBlocks: func(p *peer.Peer, msg *wire.MsgGetBlocks) { 402 ok <- msg 403 }, 404 OnGetHeaders: func(p *peer.Peer, msg *wire.MsgGetHeaders) { 405 ok <- msg 406 }, 407 OnGetCFilters: func(p *peer.Peer, msg *wire.MsgGetCFilters) { 408 ok <- msg 409 }, 410 OnGetCFHeaders: func(p *peer.Peer, msg *wire.MsgGetCFHeaders) { 411 ok <- msg 412 }, 413 OnGetCFCheckpt: func(p *peer.Peer, msg *wire.MsgGetCFCheckpt) { 414 ok <- msg 415 }, 416 OnCFilter: func(p *peer.Peer, msg *wire.MsgCFilter) { 417 ok <- msg 418 }, 419 OnCFHeaders: func(p *peer.Peer, msg *wire.MsgCFHeaders) { 420 ok <- msg 421 }, 422 OnFeeFilter: func(p *peer.Peer, msg *wire.MsgFeeFilter) { 423 ok <- msg 424 }, 425 OnFilterAdd: func(p *peer.Peer, msg *wire.MsgFilterAdd) { 426 ok <- msg 427 }, 428 OnFilterClear: func(p *peer.Peer, msg *wire.MsgFilterClear) { 429 ok <- msg 430 }, 431 OnFilterLoad: func(p *peer.Peer, msg *wire.MsgFilterLoad) { 432 ok <- msg 433 }, 434 OnMerkleBlock: func(p *peer.Peer, msg *wire.MsgMerkleBlock) { 435 ok <- msg 436 }, 437 OnVersion: func(p *peer.Peer, msg *wire.MsgVersion) *wire.MsgReject { 438 ok <- msg 439 return nil 440 }, 441 OnVerAck: func(p *peer.Peer, msg *wire.MsgVerAck) { 442 verack <- struct{}{} 443 }, 444 OnReject: func(p *peer.Peer, msg *wire.MsgReject) { 445 ok <- msg 446 }, 447 OnSendHeaders: func(p *peer.Peer, msg *wire.MsgSendHeaders) { 448 ok <- msg 449 }, 450 }, 451 UserAgentName: "peer", 452 UserAgentVersion: "1.0", 453 UserAgentComments: []string{"comment"}, 454 ChainParams: &chaincfg.MainNetParams, 455 Services: wire.SFNodeBloom, 456 TrickleInterval: time.Second * 10, 457 AllowSelfConns: true, 458 } 459 inConn, outConn := pipe( 460 &conn{raddr: "10.0.0.1:9246"}, 461 &conn{raddr: "10.0.0.2:9246"}, 462 ) 463 inPeer := peer.NewInboundPeer(peerCfg) 464 inPeer.AssociateConnection(inConn) 465 466 peerCfg.Listeners = peer.MessageListeners{ 467 OnVerAck: func(p *peer.Peer, msg *wire.MsgVerAck) { 468 verack <- struct{}{} 469 }, 470 } 471 outPeer, err := peer.NewOutboundPeer(peerCfg, "10.0.0.1:9246") 472 if err != nil { 473 t.Errorf("NewOutboundPeer: unexpected err %v\n", err) 474 return 475 } 476 outPeer.AssociateConnection(outConn) 477 478 for i := 0; i < 2; i++ { 479 select { 480 case <-verack: 481 case <-time.After(time.Second * 1): 482 t.Errorf("TestPeerListeners: verack timeout\n") 483 return 484 } 485 } 486 487 tests := []struct { 488 listener string 489 msg wire.Message 490 }{ 491 { 492 "OnGetAddr", 493 wire.NewMsgGetAddr(), 494 }, 495 { 496 "OnAddr", 497 wire.NewMsgAddr(), 498 }, 499 { 500 "OnPing", 501 wire.NewMsgPing(42), 502 }, 503 { 504 "OnPong", 505 wire.NewMsgPong(42), 506 }, 507 { 508 "OnAlert", 509 wire.NewMsgAlert([]byte("payload"), []byte("signature")), 510 }, 511 { 512 "OnMemPool", 513 wire.NewMsgMemPool(), 514 }, 515 { 516 "OnTx", 517 wire.NewMsgTx(wire.TxVersion), 518 }, 519 { 520 "OnBlock", 521 wire.NewMsgBlock(wire.NewBlockHeader(1, 522 &chainhash.Hash{}, &chainhash.Hash{}, &chainhash.Hash{}, 1, 1)), 523 }, 524 { 525 "OnInv", 526 wire.NewMsgInv(), 527 }, 528 { 529 "OnHeaders", 530 wire.NewMsgHeaders(), 531 }, 532 { 533 "OnNotFound", 534 wire.NewMsgNotFound(), 535 }, 536 { 537 "OnGetData", 538 wire.NewMsgGetData(), 539 }, 540 { 541 "OnGetBlocks", 542 wire.NewMsgGetBlocks(&chainhash.Hash{}), 543 }, 544 { 545 "OnGetHeaders", 546 wire.NewMsgGetHeaders(), 547 }, 548 { 549 "OnGetCFilters", 550 wire.NewMsgGetCFilters(wire.GCSFilterRegular, 0, &chainhash.Hash{}), 551 }, 552 { 553 "OnGetCFHeaders", 554 wire.NewMsgGetCFHeaders(wire.GCSFilterRegular, 0, &chainhash.Hash{}), 555 }, 556 { 557 "OnGetCFCheckpt", 558 wire.NewMsgGetCFCheckpt(wire.GCSFilterRegular, &chainhash.Hash{}), 559 }, 560 { 561 "OnCFilter", 562 wire.NewMsgCFilter(wire.GCSFilterRegular, &chainhash.Hash{}, 563 []byte("payload")), 564 }, 565 { 566 "OnCFHeaders", 567 wire.NewMsgCFHeaders(), 568 }, 569 { 570 "OnFeeFilter", 571 wire.NewMsgFeeFilter(15000), 572 }, 573 { 574 "OnFilterAdd", 575 wire.NewMsgFilterAdd([]byte{0x01}), 576 }, 577 { 578 "OnFilterClear", 579 wire.NewMsgFilterClear(), 580 }, 581 { 582 "OnFilterLoad", 583 wire.NewMsgFilterLoad([]byte{0x01}, 10, 0, wire.BloomUpdateNone), 584 }, 585 { 586 "OnMerkleBlock", 587 wire.NewMsgMerkleBlock(wire.NewBlockHeader(1, 588 &chainhash.Hash{}, &chainhash.Hash{}, &chainhash.Hash{}, 1, 1)), 589 }, 590 // only one version message is allowed 591 // only one verack message is allowed 592 { 593 "OnReject", 594 wire.NewMsgReject("block", wire.RejectDuplicate, "dupe block"), 595 }, 596 { 597 "OnSendHeaders", 598 wire.NewMsgSendHeaders(), 599 }, 600 } 601 t.Logf("Running %d tests", len(tests)) 602 for _, test := range tests { 603 // Queue the test message 604 outPeer.QueueMessage(test.msg, nil) 605 select { 606 case <-ok: 607 case <-time.After(time.Second * 1): 608 t.Errorf("TestPeerListeners: %s timeout", test.listener) 609 return 610 } 611 } 612 inPeer.Disconnect() 613 outPeer.Disconnect() 614 } 615 616 // TestOutboundPeer tests that the outbound peer works as expected. 617 func TestOutboundPeer(t *testing.T) { 618 619 peerCfg := &peer.Config{ 620 NewestBlock: func() (*chainhash.Hash, int32, error) { 621 return nil, 0, errors.New("newest block not found") 622 }, 623 UserAgentName: "peer", 624 UserAgentVersion: "1.0", 625 UserAgentComments: []string{"comment"}, 626 ChainParams: &chaincfg.MainNetParams, 627 Services: 0, 628 TrickleInterval: time.Second * 10, 629 AllowSelfConns: true, 630 } 631 632 r, w := io.Pipe() 633 c := &conn{raddr: "10.0.0.1:9246", Writer: w, Reader: r} 634 635 p, err := peer.NewOutboundPeer(peerCfg, "10.0.0.1:9246") 636 if err != nil { 637 t.Errorf("NewOutboundPeer: unexpected err - %v\n", err) 638 return 639 } 640 641 // Test trying to connect twice. 642 p.AssociateConnection(c) 643 p.AssociateConnection(c) 644 645 disconnected := make(chan struct{}) 646 go func() { 647 p.WaitForDisconnect() 648 disconnected <- struct{}{} 649 }() 650 651 select { 652 case <-disconnected: 653 close(disconnected) 654 case <-time.After(time.Second): 655 t.Fatal("Peer did not automatically disconnect.") 656 } 657 658 if p.Connected() { 659 t.Fatalf("Should not be connected as NewestBlock produces error.") 660 } 661 662 // Test Queue Inv 663 fakeBlockHash := &chainhash.Hash{0: 0x00, 1: 0x01} 664 fakeInv := wire.NewInvVect(wire.InvTypeBlock, fakeBlockHash) 665 666 // Should be noops as the peer could not connect. 667 p.QueueInventory(fakeInv) 668 p.AddKnownInventory(fakeInv) 669 p.QueueInventory(fakeInv) 670 671 fakeMsg := wire.NewMsgVerAck() 672 p.QueueMessage(fakeMsg, nil) 673 done := make(chan struct{}) 674 p.QueueMessage(fakeMsg, done) 675 <-done 676 p.Disconnect() 677 678 // Test NewestBlock 679 var newestBlock = func() (*chainhash.Hash, int32, error) { 680 hashStr := "14a0810ac680a3eb3f82edc878cea25ec41d6b790744e5daeef" 681 hash, err := chainhash.NewHashFromStr(hashStr) 682 if err != nil { 683 return nil, 0, err 684 } 685 return hash, 234439, nil 686 } 687 688 peerCfg.NewestBlock = newestBlock 689 r1, w1 := io.Pipe() 690 c1 := &conn{raddr: "10.0.0.1:9246", Writer: w1, Reader: r1} 691 p1, err := peer.NewOutboundPeer(peerCfg, "10.0.0.1:9246") 692 if err != nil { 693 t.Errorf("NewOutboundPeer: unexpected err - %v\n", err) 694 return 695 } 696 p1.AssociateConnection(c1) 697 698 // Test update latest block 699 latestBlockHash, err := chainhash.NewHashFromStr("1a63f9cdff1752e6375c8c76e543a71d239e1a2e5c6db1aa679") 700 if err != nil { 701 t.Errorf("NewHashFromStr: unexpected err %v\n", err) 702 return 703 } 704 p1.UpdateLastAnnouncedBlock(latestBlockHash) 705 p1.UpdateLastBlockHeight(234440) 706 if p1.LastAnnouncedBlock() != latestBlockHash { 707 t.Errorf("LastAnnouncedBlock: wrong block - got %v, want %v", 708 p1.LastAnnouncedBlock(), latestBlockHash) 709 return 710 } 711 712 // Test Queue Inv after connection 713 p1.QueueInventory(fakeInv) 714 p1.Disconnect() 715 716 // Test regression 717 peerCfg.ChainParams = &chaincfg.RegressionNetParams 718 peerCfg.Services = wire.SFNodeBloom 719 r2, w2 := io.Pipe() 720 c2 := &conn{raddr: "10.0.0.1:9246", Writer: w2, Reader: r2} 721 p2, err := peer.NewOutboundPeer(peerCfg, "10.0.0.1:9246") 722 if err != nil { 723 t.Errorf("NewOutboundPeer: unexpected err - %v\n", err) 724 return 725 } 726 p2.AssociateConnection(c2) 727 728 // Test PushXXX 729 var addrs []*wire.NetAddress 730 for i := 0; i < 5; i++ { 731 na := wire.NetAddress{} 732 addrs = append(addrs, &na) 733 } 734 if _, err := p2.PushAddrMsg(addrs); err != nil { 735 t.Errorf("PushAddrMsg: unexpected err %v\n", err) 736 return 737 } 738 if err := p2.PushGetBlocksMsg(nil, &chainhash.Hash{}); err != nil { 739 t.Errorf("PushGetBlocksMsg: unexpected err %v\n", err) 740 return 741 } 742 if err := p2.PushGetHeadersMsg(nil, &chainhash.Hash{}); err != nil { 743 t.Errorf("PushGetHeadersMsg: unexpected err %v\n", err) 744 return 745 } 746 747 p2.PushRejectMsg("block", wire.RejectMalformed, "malformed", nil, false) 748 p2.PushRejectMsg("block", wire.RejectInvalid, "invalid", nil, false) 749 750 // Test Queue Messages 751 p2.QueueMessage(wire.NewMsgGetAddr(), nil) 752 p2.QueueMessage(wire.NewMsgPing(1), nil) 753 p2.QueueMessage(wire.NewMsgMemPool(), nil) 754 p2.QueueMessage(wire.NewMsgGetData(), nil) 755 p2.QueueMessage(wire.NewMsgGetHeaders(), nil) 756 p2.QueueMessage(wire.NewMsgFeeFilter(20000), nil) 757 758 p2.Disconnect() 759 } 760 761 // Tests that the node disconnects from peers with an unsupported protocol 762 // version. 763 func TestUnsupportedVersionPeer(t *testing.T) { 764 peerCfg := &peer.Config{ 765 UserAgentName: "peer", 766 UserAgentVersion: "1.0", 767 UserAgentComments: []string{"comment"}, 768 ChainParams: &chaincfg.MainNetParams, 769 Services: 0, 770 TrickleInterval: time.Second * 10, 771 AllowSelfConns: true, 772 } 773 774 localNA := wire.NewNetAddressIPPort( 775 net.ParseIP("10.0.0.1"), 776 uint16(9246), 777 wire.SFNodeNetwork, 778 ) 779 remoteNA := wire.NewNetAddressIPPort( 780 net.ParseIP("10.0.0.2"), 781 uint16(9246), 782 wire.SFNodeNetwork, 783 ) 784 localConn, remoteConn := pipe( 785 &conn{laddr: "10.0.0.1:9246", raddr: "10.0.0.2:9246"}, 786 &conn{laddr: "10.0.0.2:9246", raddr: "10.0.0.1:9246"}, 787 ) 788 789 p, err := peer.NewOutboundPeer(peerCfg, "10.0.0.1:9246") 790 if err != nil { 791 t.Fatalf("NewOutboundPeer: unexpected err - %v\n", err) 792 } 793 p.AssociateConnection(localConn) 794 795 // Read outbound messages to peer into a channel 796 outboundMessages := make(chan wire.Message) 797 go func() { 798 for { 799 _, msg, _, err := wire.ReadMessageN( 800 remoteConn, 801 p.ProtocolVersion(), 802 peerCfg.ChainParams.Net, 803 ) 804 if err == io.EOF { 805 close(outboundMessages) 806 return 807 } 808 if err != nil { 809 t.Errorf("Error reading message from local node: %v\n", err) 810 return 811 } 812 813 outboundMessages <- msg 814 } 815 }() 816 817 // Read version message sent to remote peer 818 select { 819 case msg := <-outboundMessages: 820 if _, ok := msg.(*wire.MsgVersion); !ok { 821 t.Fatalf("Expected version message, got [%s]", msg.Command()) 822 } 823 case <-time.After(time.Second): 824 t.Fatal("Peer did not send version message") 825 } 826 827 // Remote peer writes version message advertising invalid protocol version 1 828 invalidVersionMsg := wire.NewMsgVersion(remoteNA, localNA, 0, 0) 829 invalidVersionMsg.ProtocolVersion = 1 830 831 _, err = wire.WriteMessageN( 832 remoteConn.Writer, 833 invalidVersionMsg, 834 uint32(invalidVersionMsg.ProtocolVersion), 835 peerCfg.ChainParams.Net, 836 ) 837 if err != nil { 838 t.Fatalf("wire.WriteMessageN: unexpected err - %v\n", err) 839 } 840 841 // Expect peer to disconnect automatically 842 disconnected := make(chan struct{}) 843 go func() { 844 p.WaitForDisconnect() 845 disconnected <- struct{}{} 846 }() 847 848 select { 849 case <-disconnected: 850 close(disconnected) 851 case <-time.After(time.Second): 852 t.Fatal("Peer did not automatically disconnect") 853 } 854 855 // Expect no further outbound messages from peer 856 select { 857 case msg, chanOpen := <-outboundMessages: 858 if chanOpen { 859 t.Fatalf("Expected no further messages, received [%s]", msg.Command()) 860 } 861 case <-time.After(time.Second): 862 t.Fatal("Timeout waiting for remote reader to close") 863 } 864 } 865 866 // TestDuplicateVersionMsg ensures that receiving a version message after one 867 // has already been received results in the peer being disconnected. 868 func TestDuplicateVersionMsg(t *testing.T) { 869 // Create a pair of peers that are connected to each other using a fake 870 // connection. 871 verack := make(chan struct{}) 872 peerCfg := &peer.Config{ 873 Listeners: peer.MessageListeners{ 874 OnVerAck: func(p *peer.Peer, msg *wire.MsgVerAck) { 875 verack <- struct{}{} 876 }, 877 }, 878 UserAgentName: "peer", 879 UserAgentVersion: "1.0", 880 ChainParams: &chaincfg.MainNetParams, 881 Services: 0, 882 AllowSelfConns: true, 883 } 884 inConn, outConn := pipe( 885 &conn{laddr: "10.0.0.1:9108", raddr: "10.0.0.2:9108"}, 886 &conn{laddr: "10.0.0.2:9108", raddr: "10.0.0.1:9108"}, 887 ) 888 outPeer, err := peer.NewOutboundPeer(peerCfg, inConn.laddr) 889 if err != nil { 890 t.Fatalf("NewOutboundPeer: unexpected err: %v\n", err) 891 } 892 outPeer.AssociateConnection(outConn) 893 inPeer := peer.NewInboundPeer(peerCfg) 894 inPeer.AssociateConnection(inConn) 895 // Wait for the veracks from the initial protocol version negotiation. 896 for i := 0; i < 2; i++ { 897 select { 898 case <-verack: 899 case <-time.After(time.Second): 900 t.Fatal("verack timeout") 901 } 902 } 903 // Queue a duplicate version message from the outbound peer and wait until 904 // it is sent. 905 done := make(chan struct{}) 906 outPeer.QueueMessage(&wire.MsgVersion{}, done) 907 select { 908 case <-done: 909 case <-time.After(time.Second): 910 t.Fatal("send duplicate version timeout") 911 } 912 // Ensure the peer that is the recipient of the duplicate version closes the 913 // connection. 914 disconnected := make(chan struct{}, 1) 915 go func() { 916 inPeer.WaitForDisconnect() 917 disconnected <- struct{}{} 918 }() 919 select { 920 case <-disconnected: 921 case <-time.After(time.Second): 922 t.Fatal("peer did not disconnect") 923 } 924 } 925 926 // TestUpdateLastBlockHeight ensures the last block height is set properly 927 // during the initial version negotiation and is only allowed to advance to 928 // higher values via the associated update function. 929 func TestUpdateLastBlockHeight(t *testing.T) { 930 // Create a pair of peers that are connected to each other using a fake 931 // connection and the remote peer starting at height 100. 932 const remotePeerHeight = 100 933 verack := make(chan struct{}) 934 peerCfg := peer.Config{ 935 Listeners: peer.MessageListeners{ 936 OnVerAck: func(p *peer.Peer, msg *wire.MsgVerAck) { 937 verack <- struct{}{} 938 }, 939 }, 940 UserAgentName: "peer", 941 UserAgentVersion: "1.0", 942 ChainParams: &chaincfg.MainNetParams, 943 Services: 0, 944 AllowSelfConns: true, 945 } 946 remotePeerCfg := peerCfg 947 remotePeerCfg.NewestBlock = func() (*chainhash.Hash, int32, error) { 948 return &chainhash.Hash{}, remotePeerHeight, nil 949 } 950 inConn, outConn := pipe( 951 &conn{laddr: "10.0.0.1:9108", raddr: "10.0.0.2:9108"}, 952 &conn{laddr: "10.0.0.2:9108", raddr: "10.0.0.1:9108"}, 953 ) 954 localPeer, err := peer.NewOutboundPeer(&peerCfg, inConn.laddr) 955 if err != nil { 956 t.Fatalf("NewOutboundPeer: unexpected err: %v\n", err) 957 } 958 localPeer.AssociateConnection(outConn) 959 inPeer := peer.NewInboundPeer(&remotePeerCfg) 960 inPeer.AssociateConnection(inConn) 961 962 // Wait for the veracks from the initial protocol version negotiation. 963 for i := 0; i < 2; i++ { 964 select { 965 case <-verack: 966 case <-time.After(time.Second): 967 t.Fatal("verack timeout") 968 } 969 } 970 971 // Ensure the latest block height starts at the value reported by the remote 972 // peer via its version message. 973 if height := localPeer.LastBlock(); height != remotePeerHeight { 974 t.Fatalf("wrong starting height - got %d, want %d", height, 975 remotePeerHeight) 976 } 977 978 // Ensure the latest block height is not allowed to go backwards. 979 localPeer.UpdateLastBlockHeight(remotePeerHeight - 1) 980 if height := localPeer.LastBlock(); height != remotePeerHeight { 981 t.Fatalf("height allowed to go backwards - got %d, want %d", height, 982 remotePeerHeight) 983 } 984 985 // Ensure the latest block height is allowed to advance. 986 localPeer.UpdateLastBlockHeight(remotePeerHeight + 1) 987 if height := localPeer.LastBlock(); height != remotePeerHeight+1 { 988 t.Fatalf("height not allowed to advance - got %d, want %d", height, 989 remotePeerHeight+1) 990 } 991 }