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  }