github.com/ethereum/go-ethereum@v1.16.1/p2p/dial_test.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package p2p
    18  
    19  import (
    20  	"context"
    21  	"errors"
    22  	"fmt"
    23  	"math/rand"
    24  	"net"
    25  	"net/netip"
    26  	"reflect"
    27  	"sync"
    28  	"testing"
    29  	"time"
    30  
    31  	"github.com/ethereum/go-ethereum/common/mclock"
    32  	"github.com/ethereum/go-ethereum/internal/testlog"
    33  	"github.com/ethereum/go-ethereum/log"
    34  	"github.com/ethereum/go-ethereum/p2p/enode"
    35  	"github.com/ethereum/go-ethereum/p2p/netutil"
    36  )
    37  
    38  // This test checks that dynamic dials are launched from discovery results.
    39  func TestDialSchedDynDial(t *testing.T) {
    40  	t.Parallel()
    41  
    42  	config := dialConfig{
    43  		maxActiveDials: 5,
    44  		maxDialPeers:   4,
    45  	}
    46  	runDialTest(t, config, []dialTestRound{
    47  		// 3 out of 4 peers are connected, leaving 2 dial slots.
    48  		// 9 nodes are discovered, but only 2 are dialed.
    49  		{
    50  			peersAdded: []*conn{
    51  				{flags: staticDialedConn, node: newNode(uintID(0x00), "")},
    52  				{flags: dynDialedConn, node: newNode(uintID(0x01), "")},
    53  				{flags: dynDialedConn, node: newNode(uintID(0x02), "")},
    54  			},
    55  			discovered: []*enode.Node{
    56  				newNode(uintID(0x00), "127.0.0.1:30303"), // not dialed because already connected as static peer
    57  				newNode(uintID(0x02), "127.0.0.1:30303"), // ...
    58  				newNode(uintID(0x03), "127.0.0.1:30303"),
    59  				newNode(uintID(0x04), "127.0.0.1:30303"),
    60  				newNode(uintID(0x05), "127.0.0.1:30303"), // not dialed because there are only two slots
    61  				newNode(uintID(0x06), "127.0.0.1:30303"), // ...
    62  				newNode(uintID(0x07), "127.0.0.1:30303"), // ...
    63  				newNode(uintID(0x08), "127.0.0.1:30303"), // ...
    64  			},
    65  			wantNewDials: []*enode.Node{
    66  				newNode(uintID(0x03), "127.0.0.1:30303"),
    67  				newNode(uintID(0x04), "127.0.0.1:30303"),
    68  			},
    69  		},
    70  
    71  		// One dial completes, freeing one dial slot.
    72  		{
    73  			failed: []enode.ID{
    74  				uintID(0x04),
    75  			},
    76  			wantNewDials: []*enode.Node{
    77  				newNode(uintID(0x05), "127.0.0.1:30303"),
    78  			},
    79  		},
    80  
    81  		// Dial to 0x03 completes, filling the last remaining peer slot.
    82  		{
    83  			succeeded: []enode.ID{
    84  				uintID(0x03),
    85  			},
    86  			failed: []enode.ID{
    87  				uintID(0x05),
    88  			},
    89  			discovered: []*enode.Node{
    90  				newNode(uintID(0x09), "127.0.0.1:30303"), // not dialed because there are no free slots
    91  			},
    92  		},
    93  
    94  		// 3 peers drop off, creating 6 dial slots. Check that 5 of those slots
    95  		// (i.e. up to maxActiveDialTasks) are used.
    96  		{
    97  			peersRemoved: []enode.ID{
    98  				uintID(0x00),
    99  				uintID(0x01),
   100  				uintID(0x02),
   101  			},
   102  			discovered: []*enode.Node{
   103  				newNode(uintID(0x0a), "127.0.0.1:30303"),
   104  				newNode(uintID(0x0b), "127.0.0.1:30303"),
   105  				newNode(uintID(0x0c), "127.0.0.1:30303"),
   106  				newNode(uintID(0x0d), "127.0.0.1:30303"),
   107  				newNode(uintID(0x0f), "127.0.0.1:30303"),
   108  			},
   109  			wantNewDials: []*enode.Node{
   110  				newNode(uintID(0x06), "127.0.0.1:30303"),
   111  				newNode(uintID(0x07), "127.0.0.1:30303"),
   112  				newNode(uintID(0x08), "127.0.0.1:30303"),
   113  				newNode(uintID(0x09), "127.0.0.1:30303"),
   114  				newNode(uintID(0x0a), "127.0.0.1:30303"),
   115  			},
   116  		},
   117  	})
   118  }
   119  
   120  // This test checks that candidates that do not match the netrestrict list are not dialed.
   121  func TestDialSchedNetRestrict(t *testing.T) {
   122  	t.Parallel()
   123  
   124  	nodes := []*enode.Node{
   125  		newNode(uintID(0x01), "127.0.0.1:30303"),
   126  		newNode(uintID(0x02), "127.0.0.2:30303"),
   127  		newNode(uintID(0x03), "127.0.0.3:30303"),
   128  		newNode(uintID(0x04), "127.0.0.4:30303"),
   129  		newNode(uintID(0x05), "127.0.2.5:30303"),
   130  		newNode(uintID(0x06), "127.0.2.6:30303"),
   131  		newNode(uintID(0x07), "127.0.2.7:30303"),
   132  		newNode(uintID(0x08), "127.0.2.8:30303"),
   133  	}
   134  	config := dialConfig{
   135  		netRestrict:    new(netutil.Netlist),
   136  		maxActiveDials: 10,
   137  		maxDialPeers:   10,
   138  	}
   139  	config.netRestrict.Add("127.0.2.0/24")
   140  	runDialTest(t, config, []dialTestRound{
   141  		{
   142  			discovered:   nodes,
   143  			wantNewDials: nodes[4:8],
   144  		},
   145  		{
   146  			succeeded: []enode.ID{
   147  				nodes[4].ID(),
   148  				nodes[5].ID(),
   149  				nodes[6].ID(),
   150  				nodes[7].ID(),
   151  			},
   152  		},
   153  	})
   154  }
   155  
   156  // This test checks that static dials work and obey the limits.
   157  func TestDialSchedStaticDial(t *testing.T) {
   158  	t.Parallel()
   159  
   160  	config := dialConfig{
   161  		maxActiveDials: 5,
   162  		maxDialPeers:   4,
   163  	}
   164  	runDialTest(t, config, []dialTestRound{
   165  		// Static dials are launched for the nodes that
   166  		// aren't yet connected.
   167  		{
   168  			peersAdded: []*conn{
   169  				{flags: dynDialedConn, node: newNode(uintID(0x01), "127.0.0.1:30303")},
   170  				{flags: dynDialedConn, node: newNode(uintID(0x02), "127.0.0.2:30303")},
   171  			},
   172  			update: func(d *dialScheduler) {
   173  				// These two are not dialed because they're already connected
   174  				// as dynamic peers.
   175  				d.addStatic(newNode(uintID(0x01), "127.0.0.1:30303"))
   176  				d.addStatic(newNode(uintID(0x02), "127.0.0.2:30303"))
   177  				// These nodes will be dialed:
   178  				d.addStatic(newNode(uintID(0x03), "127.0.0.3:30303"))
   179  				d.addStatic(newNode(uintID(0x04), "127.0.0.4:30303"))
   180  				d.addStatic(newNode(uintID(0x05), "127.0.0.5:30303"))
   181  				d.addStatic(newNode(uintID(0x06), "127.0.0.6:30303"))
   182  				d.addStatic(newNode(uintID(0x07), "127.0.0.7:30303"))
   183  				d.addStatic(newNode(uintID(0x08), "127.0.0.8:30303"))
   184  				d.addStatic(newNode(uintID(0x09), "127.0.0.9:30303"))
   185  			},
   186  			wantNewDials: []*enode.Node{
   187  				newNode(uintID(0x03), "127.0.0.3:30303"),
   188  				newNode(uintID(0x04), "127.0.0.4:30303"),
   189  				newNode(uintID(0x05), "127.0.0.5:30303"),
   190  				newNode(uintID(0x06), "127.0.0.6:30303"),
   191  			},
   192  		},
   193  		// Dial to 0x03 completes, filling a peer slot. One slot remains,
   194  		// two dials are launched to attempt to fill it.
   195  		{
   196  			succeeded: []enode.ID{
   197  				uintID(0x03),
   198  			},
   199  			failed: []enode.ID{
   200  				uintID(0x04),
   201  				uintID(0x05),
   202  				uintID(0x06),
   203  			},
   204  			wantResolves: map[enode.ID]*enode.Node{
   205  				uintID(0x04): nil,
   206  				uintID(0x05): nil,
   207  				uintID(0x06): nil,
   208  			},
   209  			wantNewDials: []*enode.Node{
   210  				newNode(uintID(0x08), "127.0.0.8:30303"),
   211  				newNode(uintID(0x09), "127.0.0.9:30303"),
   212  			},
   213  		},
   214  		// Peer 0x01 drops and 0x07 connects as inbound peer.
   215  		// Only 0x01 is dialed.
   216  		{
   217  			peersAdded: []*conn{
   218  				{flags: inboundConn, node: newNode(uintID(0x07), "127.0.0.7:30303")},
   219  			},
   220  			peersRemoved: []enode.ID{
   221  				uintID(0x01),
   222  			},
   223  			wantNewDials: []*enode.Node{
   224  				newNode(uintID(0x01), "127.0.0.1:30303"),
   225  			},
   226  		},
   227  	})
   228  }
   229  
   230  // This test checks that removing static nodes stops connecting to them.
   231  func TestDialSchedRemoveStatic(t *testing.T) {
   232  	t.Parallel()
   233  
   234  	config := dialConfig{
   235  		maxActiveDials: 1,
   236  		maxDialPeers:   1,
   237  	}
   238  	runDialTest(t, config, []dialTestRound{
   239  		// Add static nodes.
   240  		{
   241  			update: func(d *dialScheduler) {
   242  				d.addStatic(newNode(uintID(0x01), "127.0.0.1:30303"))
   243  				d.addStatic(newNode(uintID(0x02), "127.0.0.2:30303"))
   244  				d.addStatic(newNode(uintID(0x03), "127.0.0.3:30303"))
   245  			},
   246  			wantNewDials: []*enode.Node{
   247  				newNode(uintID(0x01), "127.0.0.1:30303"),
   248  			},
   249  		},
   250  		// Dial to 0x01 fails.
   251  		{
   252  			failed: []enode.ID{
   253  				uintID(0x01),
   254  			},
   255  			wantResolves: map[enode.ID]*enode.Node{
   256  				uintID(0x01): nil,
   257  			},
   258  			wantNewDials: []*enode.Node{
   259  				newNode(uintID(0x02), "127.0.0.2:30303"),
   260  			},
   261  		},
   262  		// All static nodes are removed. 0x01 is in history, 0x02 is being
   263  		// dialed, 0x03 is in staticPool.
   264  		{
   265  			update: func(d *dialScheduler) {
   266  				d.removeStatic(newNode(uintID(0x01), "127.0.0.1:30303"))
   267  				d.removeStatic(newNode(uintID(0x02), "127.0.0.2:30303"))
   268  				d.removeStatic(newNode(uintID(0x03), "127.0.0.3:30303"))
   269  			},
   270  			failed: []enode.ID{
   271  				uintID(0x02),
   272  			},
   273  			wantResolves: map[enode.ID]*enode.Node{
   274  				uintID(0x02): nil,
   275  			},
   276  		},
   277  		// Since all static nodes are removed, they should not be dialed again.
   278  		{}, {}, {},
   279  	})
   280  }
   281  
   282  // This test checks that static dials are selected at random.
   283  func TestDialSchedManyStaticNodes(t *testing.T) {
   284  	t.Parallel()
   285  
   286  	config := dialConfig{maxDialPeers: 2}
   287  	runDialTest(t, config, []dialTestRound{
   288  		{
   289  			peersAdded: []*conn{
   290  				{flags: dynDialedConn, node: newNode(uintID(0xFFFE), "")},
   291  				{flags: dynDialedConn, node: newNode(uintID(0xFFFF), "")},
   292  			},
   293  			update: func(d *dialScheduler) {
   294  				for id := uint16(0); id < 2000; id++ {
   295  					n := newNode(uintID(id), "127.0.0.1:30303")
   296  					d.addStatic(n)
   297  				}
   298  			},
   299  		},
   300  		{
   301  			peersRemoved: []enode.ID{
   302  				uintID(0xFFFE),
   303  				uintID(0xFFFF),
   304  			},
   305  			wantNewDials: []*enode.Node{
   306  				newNode(uintID(0x0085), "127.0.0.1:30303"),
   307  				newNode(uintID(0x02dc), "127.0.0.1:30303"),
   308  				newNode(uintID(0x0285), "127.0.0.1:30303"),
   309  				newNode(uintID(0x00cb), "127.0.0.1:30303"),
   310  			},
   311  		},
   312  	})
   313  }
   314  
   315  // This test checks that past dials are not retried for some time.
   316  func TestDialSchedHistory(t *testing.T) {
   317  	t.Parallel()
   318  
   319  	config := dialConfig{
   320  		maxActiveDials: 3,
   321  		maxDialPeers:   3,
   322  	}
   323  	runDialTest(t, config, []dialTestRound{
   324  		{
   325  			update: func(d *dialScheduler) {
   326  				d.addStatic(newNode(uintID(0x01), "127.0.0.1:30303"))
   327  				d.addStatic(newNode(uintID(0x02), "127.0.0.2:30303"))
   328  				d.addStatic(newNode(uintID(0x03), "127.0.0.3:30303"))
   329  			},
   330  			wantNewDials: []*enode.Node{
   331  				newNode(uintID(0x01), "127.0.0.1:30303"),
   332  				newNode(uintID(0x02), "127.0.0.2:30303"),
   333  				newNode(uintID(0x03), "127.0.0.3:30303"),
   334  			},
   335  		},
   336  		// No new tasks are launched in this round because all static
   337  		// nodes are either connected or still being dialed.
   338  		{
   339  			succeeded: []enode.ID{
   340  				uintID(0x01),
   341  				uintID(0x02),
   342  			},
   343  			failed: []enode.ID{
   344  				uintID(0x03),
   345  			},
   346  			wantResolves: map[enode.ID]*enode.Node{
   347  				uintID(0x03): nil,
   348  			},
   349  		},
   350  		// Nothing happens in this round because we're waiting for
   351  		// node 0x3's history entry to expire.
   352  		{},
   353  		// The cache entry for node 0x03 has expired and is retried.
   354  		{
   355  			wantNewDials: []*enode.Node{
   356  				newNode(uintID(0x03), "127.0.0.3:30303"),
   357  			},
   358  		},
   359  	})
   360  }
   361  
   362  func TestDialSchedResolve(t *testing.T) {
   363  	t.Parallel()
   364  
   365  	config := dialConfig{
   366  		maxActiveDials: 1,
   367  		maxDialPeers:   1,
   368  	}
   369  	node := newNode(uintID(0x01), "")
   370  	resolved := newNode(uintID(0x01), "127.0.0.1:30303")
   371  	resolved2 := newNode(uintID(0x01), "127.0.0.55:30303")
   372  	runDialTest(t, config, []dialTestRound{
   373  		{
   374  			update: func(d *dialScheduler) {
   375  				d.addStatic(node)
   376  			},
   377  			wantResolves: map[enode.ID]*enode.Node{
   378  				uintID(0x01): resolved,
   379  			},
   380  			wantNewDials: []*enode.Node{
   381  				resolved,
   382  			},
   383  		},
   384  		{
   385  			failed: []enode.ID{
   386  				uintID(0x01),
   387  			},
   388  			wantResolves: map[enode.ID]*enode.Node{
   389  				uintID(0x01): resolved2,
   390  			},
   391  			wantNewDials: []*enode.Node{
   392  				resolved2,
   393  			},
   394  		},
   395  	})
   396  }
   397  
   398  func TestDialSchedDNSHostname(t *testing.T) {
   399  	t.Parallel()
   400  
   401  	config := dialConfig{
   402  		maxActiveDials: 1,
   403  		maxDialPeers:   1,
   404  	}
   405  	node := newNode(uintID(0x01), ":30303").WithHostname("node-hostname")
   406  	resolved := newNode(uintID(0x01), "1.2.3.4:30303").WithHostname("node-hostname")
   407  	runDialTest(t, config, []dialTestRound{
   408  		{
   409  			update: func(d *dialScheduler) {
   410  				d.dnsLookupFunc = func(ctx context.Context, network string, name string) ([]netip.Addr, error) {
   411  					if name != "node-hostname" {
   412  						t.Error("wrong hostname in DNS lookup:", name)
   413  					}
   414  					result := []netip.Addr{netip.MustParseAddr("1.2.3.4")}
   415  					return result, nil
   416  				}
   417  				d.addStatic(node)
   418  			},
   419  			wantNewDials: []*enode.Node{
   420  				resolved,
   421  			},
   422  		},
   423  	})
   424  }
   425  
   426  // -------
   427  // Code below here is the framework for the tests above.
   428  
   429  type dialTestRound struct {
   430  	peersAdded   []*conn
   431  	peersRemoved []enode.ID
   432  	update       func(*dialScheduler) // called at beginning of round
   433  	discovered   []*enode.Node        // newly discovered nodes
   434  	succeeded    []enode.ID           // dials which succeed this round
   435  	failed       []enode.ID           // dials which fail this round
   436  	wantResolves map[enode.ID]*enode.Node
   437  	wantNewDials []*enode.Node // dials that should be launched in this round
   438  }
   439  
   440  func runDialTest(t *testing.T, config dialConfig, rounds []dialTestRound) {
   441  	var (
   442  		clock    = new(mclock.Simulated)
   443  		iterator = newDialTestIterator()
   444  		dialer   = newDialTestDialer()
   445  		resolver = new(dialTestResolver)
   446  		peers    = make(map[enode.ID]*conn)
   447  		setupCh  = make(chan *conn)
   448  	)
   449  
   450  	// Override config.
   451  	config.clock = clock
   452  	config.dialer = dialer
   453  	config.resolver = resolver
   454  	config.log = testlog.Logger(t, log.LvlTrace)
   455  	config.rand = rand.New(rand.NewSource(0x1111))
   456  
   457  	// Set up the dialer. The setup function below runs on the dialTask
   458  	// goroutine and adds the peer.
   459  	var dialsched *dialScheduler
   460  	setup := func(fd net.Conn, f connFlag, node *enode.Node) error {
   461  		conn := &conn{flags: f, node: node}
   462  		dialsched.peerAdded(conn)
   463  		setupCh <- conn
   464  		return nil
   465  	}
   466  	dialsched = newDialScheduler(config, iterator, setup)
   467  	defer dialsched.stop()
   468  
   469  	for i, round := range rounds {
   470  		// Apply peer set updates.
   471  		for _, c := range round.peersAdded {
   472  			if peers[c.node.ID()] != nil {
   473  				t.Fatalf("round %d: peer %v already connected", i, c.node.ID())
   474  			}
   475  			dialsched.peerAdded(c)
   476  			peers[c.node.ID()] = c
   477  		}
   478  		for _, id := range round.peersRemoved {
   479  			c := peers[id]
   480  			if c == nil {
   481  				t.Fatalf("round %d: can't remove non-existent peer %v", i, id)
   482  			}
   483  			dialsched.peerRemoved(c)
   484  		}
   485  
   486  		// Init round.
   487  		t.Logf("round %d (%d peers)", i, len(peers))
   488  		resolver.setAnswers(round.wantResolves)
   489  		if round.update != nil {
   490  			round.update(dialsched)
   491  		}
   492  		iterator.addNodes(round.discovered)
   493  
   494  		// Unblock dialTask goroutines.
   495  		if err := dialer.completeDials(round.succeeded, nil); err != nil {
   496  			t.Fatalf("round %d: %v", i, err)
   497  		}
   498  		for range round.succeeded {
   499  			conn := <-setupCh
   500  			peers[conn.node.ID()] = conn
   501  		}
   502  		if err := dialer.completeDials(round.failed, errors.New("oops")); err != nil {
   503  			t.Fatalf("round %d: %v", i, err)
   504  		}
   505  
   506  		// Wait for new tasks.
   507  		if err := dialer.waitForDials(round.wantNewDials); err != nil {
   508  			t.Fatalf("round %d: %v", i, err)
   509  		}
   510  		if !resolver.checkCalls() {
   511  			t.Fatalf("unexpected calls to Resolve: %v", resolver.calls)
   512  		}
   513  
   514  		clock.Run(16 * time.Second)
   515  	}
   516  }
   517  
   518  // dialTestIterator is the input iterator for dialer tests. This works a bit like a channel
   519  // with infinite buffer: nodes are added to the buffer with addNodes, which unblocks Next
   520  // and returns them from the iterator.
   521  type dialTestIterator struct {
   522  	cur *enode.Node
   523  
   524  	mu     sync.Mutex
   525  	buf    []*enode.Node
   526  	cond   *sync.Cond
   527  	closed bool
   528  }
   529  
   530  func newDialTestIterator() *dialTestIterator {
   531  	it := &dialTestIterator{}
   532  	it.cond = sync.NewCond(&it.mu)
   533  	return it
   534  }
   535  
   536  // addNodes adds nodes to the iterator buffer and unblocks Next.
   537  func (it *dialTestIterator) addNodes(nodes []*enode.Node) {
   538  	it.mu.Lock()
   539  	defer it.mu.Unlock()
   540  
   541  	it.buf = append(it.buf, nodes...)
   542  	it.cond.Signal()
   543  }
   544  
   545  // Node returns the current node.
   546  func (it *dialTestIterator) Node() *enode.Node {
   547  	return it.cur
   548  }
   549  
   550  // Next moves to the next node.
   551  func (it *dialTestIterator) Next() bool {
   552  	it.mu.Lock()
   553  	defer it.mu.Unlock()
   554  
   555  	it.cur = nil
   556  	for len(it.buf) == 0 && !it.closed {
   557  		it.cond.Wait()
   558  	}
   559  	if it.closed {
   560  		return false
   561  	}
   562  	it.cur = it.buf[0]
   563  	copy(it.buf[:], it.buf[1:])
   564  	it.buf = it.buf[:len(it.buf)-1]
   565  	return true
   566  }
   567  
   568  // Close ends the iterator, unblocking Next.
   569  func (it *dialTestIterator) Close() {
   570  	it.mu.Lock()
   571  	defer it.mu.Unlock()
   572  
   573  	it.closed = true
   574  	it.buf = nil
   575  	it.cond.Signal()
   576  }
   577  
   578  // dialTestDialer is the NodeDialer used by runDialTest.
   579  type dialTestDialer struct {
   580  	init    chan *dialTestReq
   581  	blocked map[enode.ID]*dialTestReq
   582  }
   583  
   584  type dialTestReq struct {
   585  	n       *enode.Node
   586  	unblock chan error
   587  }
   588  
   589  func newDialTestDialer() *dialTestDialer {
   590  	return &dialTestDialer{
   591  		init:    make(chan *dialTestReq),
   592  		blocked: make(map[enode.ID]*dialTestReq),
   593  	}
   594  }
   595  
   596  // Dial implements NodeDialer.
   597  func (d *dialTestDialer) Dial(ctx context.Context, n *enode.Node) (net.Conn, error) {
   598  	req := &dialTestReq{n: n, unblock: make(chan error, 1)}
   599  	select {
   600  	case d.init <- req:
   601  		select {
   602  		case err := <-req.unblock:
   603  			pipe, _ := net.Pipe()
   604  			return pipe, err
   605  		case <-ctx.Done():
   606  			return nil, ctx.Err()
   607  		}
   608  	case <-ctx.Done():
   609  		return nil, ctx.Err()
   610  	}
   611  }
   612  
   613  // waitForDials waits for calls to Dial with the given nodes as argument.
   614  // Those calls will be held blocking until completeDials is called with the same nodes.
   615  func (d *dialTestDialer) waitForDials(nodes []*enode.Node) error {
   616  	waitset := make(map[enode.ID]*enode.Node, len(nodes))
   617  	for _, n := range nodes {
   618  		waitset[n.ID()] = n
   619  	}
   620  	timeout := time.NewTimer(1 * time.Second)
   621  	defer timeout.Stop()
   622  
   623  	for len(waitset) > 0 {
   624  		select {
   625  		case req := <-d.init:
   626  			want, ok := waitset[req.n.ID()]
   627  			if !ok {
   628  				return fmt.Errorf("attempt to dial unexpected node %v", req.n.ID())
   629  			}
   630  			if !reflect.DeepEqual(req.n, want) {
   631  				return fmt.Errorf("ENR of dialed node %v does not match test", req.n.ID())
   632  			}
   633  			delete(waitset, req.n.ID())
   634  			d.blocked[req.n.ID()] = req
   635  		case <-timeout.C:
   636  			var waitlist []enode.ID
   637  			for id := range waitset {
   638  				waitlist = append(waitlist, id)
   639  			}
   640  			return fmt.Errorf("timed out waiting for dials to %v", waitlist)
   641  		}
   642  	}
   643  
   644  	return d.checkUnexpectedDial()
   645  }
   646  
   647  func (d *dialTestDialer) checkUnexpectedDial() error {
   648  	select {
   649  	case req := <-d.init:
   650  		return fmt.Errorf("attempt to dial unexpected node %v", req.n.ID())
   651  	case <-time.After(150 * time.Millisecond):
   652  		return nil
   653  	}
   654  }
   655  
   656  // completeDials unblocks calls to Dial for the given nodes.
   657  func (d *dialTestDialer) completeDials(ids []enode.ID, err error) error {
   658  	for _, id := range ids {
   659  		req := d.blocked[id]
   660  		if req == nil {
   661  			return fmt.Errorf("can't complete dial to %v", id)
   662  		}
   663  		req.unblock <- err
   664  	}
   665  	return nil
   666  }
   667  
   668  // dialTestResolver tracks calls to resolve.
   669  type dialTestResolver struct {
   670  	mu      sync.Mutex
   671  	calls   []enode.ID
   672  	answers map[enode.ID]*enode.Node
   673  }
   674  
   675  func (t *dialTestResolver) setAnswers(m map[enode.ID]*enode.Node) {
   676  	t.mu.Lock()
   677  	defer t.mu.Unlock()
   678  
   679  	t.answers = m
   680  	t.calls = nil
   681  }
   682  
   683  func (t *dialTestResolver) checkCalls() bool {
   684  	t.mu.Lock()
   685  	defer t.mu.Unlock()
   686  
   687  	for _, id := range t.calls {
   688  		if _, ok := t.answers[id]; !ok {
   689  			return false
   690  		}
   691  	}
   692  	return true
   693  }
   694  
   695  func (t *dialTestResolver) Resolve(n *enode.Node) *enode.Node {
   696  	t.mu.Lock()
   697  	defer t.mu.Unlock()
   698  
   699  	t.calls = append(t.calls, n.ID())
   700  	return t.answers[n.ID()]
   701  }