You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1797 lines
59 KiB

  1. package p2p_test
  2. import (
  3. "context"
  4. "errors"
  5. "strings"
  6. "testing"
  7. "time"
  8. "github.com/fortytw2/leaktest"
  9. "github.com/stretchr/testify/require"
  10. dbm "github.com/tendermint/tm-db"
  11. "github.com/tendermint/tendermint/internal/p2p"
  12. "github.com/tendermint/tendermint/types"
  13. )
  14. // FIXME: We should probably have some randomized property-based tests for the
  15. // PeerManager too, which runs a bunch of random operations with random peers
  16. // and ensures certain invariants always hold. The logic can be complex, with
  17. // many interactions, and it's hard to cover all scenarios with handwritten
  18. // tests.
  19. func TestPeerManagerOptions_Validate(t *testing.T) {
  20. nodeID := types.NodeID("00112233445566778899aabbccddeeff00112233")
  21. testcases := map[string]struct {
  22. options p2p.PeerManagerOptions
  23. ok bool
  24. }{
  25. "zero options is valid": {p2p.PeerManagerOptions{}, true},
  26. // PersistentPeers
  27. "valid PersistentPeers NodeID": {p2p.PeerManagerOptions{
  28. PersistentPeers: []types.NodeID{"00112233445566778899aabbccddeeff00112233"},
  29. }, true},
  30. "invalid PersistentPeers NodeID": {p2p.PeerManagerOptions{
  31. PersistentPeers: []types.NodeID{"foo"},
  32. }, false},
  33. "uppercase PersistentPeers NodeID": {p2p.PeerManagerOptions{
  34. PersistentPeers: []types.NodeID{"00112233445566778899AABBCCDDEEFF00112233"},
  35. }, false},
  36. "PersistentPeers at MaxConnected": {p2p.PeerManagerOptions{
  37. PersistentPeers: []types.NodeID{nodeID, nodeID, nodeID},
  38. MaxConnected: 3,
  39. }, true},
  40. "PersistentPeers above MaxConnected": {p2p.PeerManagerOptions{
  41. PersistentPeers: []types.NodeID{nodeID, nodeID, nodeID},
  42. MaxConnected: 2,
  43. }, false},
  44. "PersistentPeers above MaxConnected below MaxConnectedUpgrade": {p2p.PeerManagerOptions{
  45. PersistentPeers: []types.NodeID{nodeID, nodeID, nodeID},
  46. MaxConnected: 2,
  47. MaxConnectedUpgrade: 2,
  48. }, false},
  49. // MaxPeers
  50. "MaxPeers without MaxConnected": {p2p.PeerManagerOptions{
  51. MaxPeers: 3,
  52. }, false},
  53. "MaxPeers below MaxConnected+MaxConnectedUpgrade": {p2p.PeerManagerOptions{
  54. MaxPeers: 2,
  55. MaxConnected: 2,
  56. MaxConnectedUpgrade: 1,
  57. }, false},
  58. "MaxPeers at MaxConnected+MaxConnectedUpgrade": {p2p.PeerManagerOptions{
  59. MaxPeers: 3,
  60. MaxConnected: 2,
  61. MaxConnectedUpgrade: 1,
  62. }, true},
  63. // MaxRetryTime
  64. "MaxRetryTime below MinRetryTime": {p2p.PeerManagerOptions{
  65. MinRetryTime: 7 * time.Second,
  66. MaxRetryTime: 5 * time.Second,
  67. }, false},
  68. "MaxRetryTime at MinRetryTime": {p2p.PeerManagerOptions{
  69. MinRetryTime: 5 * time.Second,
  70. MaxRetryTime: 5 * time.Second,
  71. }, true},
  72. "MaxRetryTime without MinRetryTime": {p2p.PeerManagerOptions{
  73. MaxRetryTime: 5 * time.Second,
  74. }, false},
  75. // MaxRetryTimePersistent
  76. "MaxRetryTimePersistent below MinRetryTime": {p2p.PeerManagerOptions{
  77. MinRetryTime: 7 * time.Second,
  78. MaxRetryTimePersistent: 5 * time.Second,
  79. }, false},
  80. "MaxRetryTimePersistent at MinRetryTime": {p2p.PeerManagerOptions{
  81. MinRetryTime: 5 * time.Second,
  82. MaxRetryTimePersistent: 5 * time.Second,
  83. }, true},
  84. "MaxRetryTimePersistent without MinRetryTime": {p2p.PeerManagerOptions{
  85. MaxRetryTimePersistent: 5 * time.Second,
  86. }, false},
  87. }
  88. for name, tc := range testcases {
  89. tc := tc
  90. t.Run(name, func(t *testing.T) {
  91. err := tc.options.Validate()
  92. if tc.ok {
  93. require.NoError(t, err)
  94. } else {
  95. require.Error(t, err)
  96. }
  97. })
  98. }
  99. }
  100. func TestNewPeerManager(t *testing.T) {
  101. // Zero options should be valid.
  102. _, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{})
  103. require.NoError(t, err)
  104. // Invalid options should error.
  105. _, err = p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{
  106. PersistentPeers: []types.NodeID{"foo"},
  107. })
  108. require.Error(t, err)
  109. // Invalid database should error.
  110. _, err = p2p.NewPeerManager(selfID, nil, p2p.PeerManagerOptions{})
  111. require.Error(t, err)
  112. // Empty self ID should error.
  113. _, err = p2p.NewPeerManager("", nil, p2p.PeerManagerOptions{})
  114. require.Error(t, err)
  115. }
  116. func TestNewPeerManager_Persistence(t *testing.T) {
  117. aID := types.NodeID(strings.Repeat("a", 40))
  118. aAddresses := []p2p.NodeAddress{
  119. {Protocol: "tcp", NodeID: aID, Hostname: "127.0.0.1", Port: 26657, Path: "/path"},
  120. {Protocol: "memory", NodeID: aID},
  121. }
  122. bID := types.NodeID(strings.Repeat("b", 40))
  123. bAddresses := []p2p.NodeAddress{
  124. {Protocol: "tcp", NodeID: bID, Hostname: "b10c::1", Port: 26657, Path: "/path"},
  125. {Protocol: "memory", NodeID: bID},
  126. }
  127. cID := types.NodeID(strings.Repeat("c", 40))
  128. cAddresses := []p2p.NodeAddress{
  129. {Protocol: "tcp", NodeID: cID, Hostname: "host.domain", Port: 80},
  130. {Protocol: "memory", NodeID: cID},
  131. }
  132. // Create an initial peer manager and add the peers.
  133. db := dbm.NewMemDB()
  134. peerManager, err := p2p.NewPeerManager(selfID, db, p2p.PeerManagerOptions{
  135. PersistentPeers: []types.NodeID{aID},
  136. PeerScores: map[types.NodeID]p2p.PeerScore{bID: 1},
  137. })
  138. require.NoError(t, err)
  139. defer peerManager.Close()
  140. for _, addr := range append(append(aAddresses, bAddresses...), cAddresses...) {
  141. added, err := peerManager.Add(addr)
  142. require.NoError(t, err)
  143. require.True(t, added)
  144. }
  145. require.ElementsMatch(t, aAddresses, peerManager.Addresses(aID))
  146. require.ElementsMatch(t, bAddresses, peerManager.Addresses(bID))
  147. require.ElementsMatch(t, cAddresses, peerManager.Addresses(cID))
  148. require.Equal(t, map[types.NodeID]p2p.PeerScore{
  149. aID: p2p.PeerScorePersistent,
  150. bID: 1,
  151. cID: 0,
  152. }, peerManager.Scores())
  153. peerManager.Close()
  154. // Creating a new peer manager with the same database should retain the
  155. // peers, but they should have updated scores from the new PersistentPeers
  156. // configuration.
  157. peerManager, err = p2p.NewPeerManager(selfID, db, p2p.PeerManagerOptions{
  158. PersistentPeers: []types.NodeID{bID},
  159. PeerScores: map[types.NodeID]p2p.PeerScore{cID: 1},
  160. })
  161. require.NoError(t, err)
  162. defer peerManager.Close()
  163. require.ElementsMatch(t, aAddresses, peerManager.Addresses(aID))
  164. require.ElementsMatch(t, bAddresses, peerManager.Addresses(bID))
  165. require.ElementsMatch(t, cAddresses, peerManager.Addresses(cID))
  166. require.Equal(t, map[types.NodeID]p2p.PeerScore{
  167. aID: 0,
  168. bID: p2p.PeerScorePersistent,
  169. cID: 1,
  170. }, peerManager.Scores())
  171. }
  172. func TestNewPeerManager_SelfIDChange(t *testing.T) {
  173. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  174. b := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("b", 40))}
  175. db := dbm.NewMemDB()
  176. peerManager, err := p2p.NewPeerManager(selfID, db, p2p.PeerManagerOptions{})
  177. require.NoError(t, err)
  178. added, err := peerManager.Add(a)
  179. require.NoError(t, err)
  180. require.True(t, added)
  181. added, err = peerManager.Add(b)
  182. require.NoError(t, err)
  183. require.True(t, added)
  184. require.ElementsMatch(t, []types.NodeID{a.NodeID, b.NodeID}, peerManager.Peers())
  185. peerManager.Close()
  186. // If we change our selfID to one of the peers in the peer store, it
  187. // should be removed from the store.
  188. peerManager, err = p2p.NewPeerManager(a.NodeID, db, p2p.PeerManagerOptions{})
  189. require.NoError(t, err)
  190. require.Equal(t, []types.NodeID{b.NodeID}, peerManager.Peers())
  191. }
  192. func TestPeerManager_Add(t *testing.T) {
  193. aID := types.NodeID(strings.Repeat("a", 40))
  194. bID := types.NodeID(strings.Repeat("b", 40))
  195. cID := types.NodeID(strings.Repeat("c", 40))
  196. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{
  197. PersistentPeers: []types.NodeID{aID, cID},
  198. MaxPeers: 2,
  199. MaxConnected: 2,
  200. })
  201. require.NoError(t, err)
  202. // Adding a couple of addresses should work.
  203. aAddresses := []p2p.NodeAddress{
  204. {Protocol: "tcp", NodeID: aID, Hostname: "localhost"},
  205. {Protocol: "memory", NodeID: aID},
  206. }
  207. for _, addr := range aAddresses {
  208. added, err := peerManager.Add(addr)
  209. require.NoError(t, err)
  210. require.True(t, added)
  211. }
  212. require.ElementsMatch(t, aAddresses, peerManager.Addresses(aID))
  213. // Adding a different peer should be fine.
  214. bAddress := p2p.NodeAddress{Protocol: "tcp", NodeID: bID, Hostname: "localhost"}
  215. added, err := peerManager.Add(bAddress)
  216. require.NoError(t, err)
  217. require.True(t, added)
  218. require.Equal(t, []p2p.NodeAddress{bAddress}, peerManager.Addresses(bID))
  219. require.ElementsMatch(t, aAddresses, peerManager.Addresses(aID))
  220. // Adding an existing address again should be a noop.
  221. added, err = peerManager.Add(aAddresses[0])
  222. require.NoError(t, err)
  223. require.False(t, added)
  224. require.ElementsMatch(t, aAddresses, peerManager.Addresses(aID))
  225. // Adding a third peer with MaxPeers=2 should cause bID, which is
  226. // the lowest-scored peer (not in PersistentPeers), to be removed.
  227. added, err = peerManager.Add(p2p.NodeAddress{
  228. Protocol: "tcp", NodeID: cID, Hostname: "localhost"})
  229. require.NoError(t, err)
  230. require.True(t, added)
  231. require.ElementsMatch(t, []types.NodeID{aID, cID}, peerManager.Peers())
  232. // Adding an invalid address should error.
  233. _, err = peerManager.Add(p2p.NodeAddress{Path: "foo"})
  234. require.Error(t, err)
  235. // Adding self should error
  236. _, err = peerManager.Add(p2p.NodeAddress{Protocol: "memory", NodeID: selfID})
  237. require.Error(t, err)
  238. }
  239. func TestPeerManager_DialNext(t *testing.T) {
  240. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  241. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{})
  242. require.NoError(t, err)
  243. // Add an address. DialNext should return it.
  244. added, err := peerManager.Add(a)
  245. require.NoError(t, err)
  246. require.True(t, added)
  247. address, err := peerManager.DialNext(ctx)
  248. require.NoError(t, err)
  249. require.Equal(t, a, address)
  250. // Since there are no more undialed peers, the next call should block
  251. // until it times out.
  252. timeoutCtx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
  253. defer cancel()
  254. _, err = peerManager.DialNext(timeoutCtx)
  255. require.Error(t, err)
  256. require.Equal(t, context.DeadlineExceeded, err)
  257. }
  258. func TestPeerManager_DialNext_Retry(t *testing.T) {
  259. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  260. options := p2p.PeerManagerOptions{
  261. MinRetryTime: 100 * time.Millisecond,
  262. MaxRetryTime: 500 * time.Millisecond,
  263. }
  264. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), options)
  265. require.NoError(t, err)
  266. added, err := peerManager.Add(a)
  267. require.NoError(t, err)
  268. require.True(t, added)
  269. // Do five dial retries (six dials total). The retry time should double for
  270. // each failure. At the forth retry, MaxRetryTime should kick in.
  271. ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
  272. defer cancel()
  273. for i := 0; i <= 5; i++ {
  274. start := time.Now()
  275. dial, err := peerManager.DialNext(ctx)
  276. require.NoError(t, err)
  277. require.Equal(t, a, dial)
  278. elapsed := time.Since(start).Round(time.Millisecond)
  279. switch i {
  280. case 0:
  281. require.LessOrEqual(t, elapsed, options.MinRetryTime)
  282. case 1:
  283. require.GreaterOrEqual(t, elapsed, options.MinRetryTime)
  284. case 2:
  285. require.GreaterOrEqual(t, elapsed, 2*options.MinRetryTime)
  286. case 3:
  287. require.GreaterOrEqual(t, elapsed, 4*options.MinRetryTime)
  288. case 4, 5:
  289. require.GreaterOrEqual(t, elapsed, options.MaxRetryTime)
  290. require.LessOrEqual(t, elapsed, 8*options.MinRetryTime)
  291. default:
  292. require.Fail(t, "unexpected retry")
  293. }
  294. require.NoError(t, peerManager.DialFailed(a))
  295. }
  296. }
  297. func TestPeerManager_DialNext_WakeOnAdd(t *testing.T) {
  298. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  299. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{})
  300. require.NoError(t, err)
  301. // Spawn a goroutine to add a peer after a delay.
  302. go func() {
  303. time.Sleep(200 * time.Millisecond)
  304. added, err := peerManager.Add(a)
  305. require.NoError(t, err)
  306. require.True(t, added)
  307. }()
  308. // This will block until peer is added above.
  309. ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
  310. defer cancel()
  311. dial, err := peerManager.DialNext(ctx)
  312. require.NoError(t, err)
  313. require.Equal(t, a, dial)
  314. }
  315. func TestPeerManager_DialNext_WakeOnDialFailed(t *testing.T) {
  316. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{
  317. MaxConnected: 1,
  318. })
  319. require.NoError(t, err)
  320. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  321. b := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("b", 40))}
  322. // Add and dial a.
  323. added, err := peerManager.Add(a)
  324. require.NoError(t, err)
  325. require.True(t, added)
  326. dial, err := peerManager.TryDialNext()
  327. require.NoError(t, err)
  328. require.Equal(t, a, dial)
  329. // Add b. We shouldn't be able to dial it, due to MaxConnected.
  330. added, err = peerManager.Add(b)
  331. require.NoError(t, err)
  332. require.True(t, added)
  333. dial, err = peerManager.TryDialNext()
  334. require.NoError(t, err)
  335. require.Zero(t, dial)
  336. // Spawn a goroutine to fail a's dial attempt.
  337. go func() {
  338. time.Sleep(200 * time.Millisecond)
  339. require.NoError(t, peerManager.DialFailed(a))
  340. }()
  341. // This should make b available for dialing (not a, retries are disabled).
  342. ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
  343. defer cancel()
  344. dial, err = peerManager.DialNext(ctx)
  345. require.NoError(t, err)
  346. require.Equal(t, b, dial)
  347. }
  348. func TestPeerManager_DialNext_WakeOnDialFailedRetry(t *testing.T) {
  349. options := p2p.PeerManagerOptions{MinRetryTime: 200 * time.Millisecond}
  350. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), options)
  351. require.NoError(t, err)
  352. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  353. // Add a, dial it, and mark it a failure. This will start a retry timer.
  354. added, err := peerManager.Add(a)
  355. require.NoError(t, err)
  356. require.True(t, added)
  357. dial, err := peerManager.TryDialNext()
  358. require.NoError(t, err)
  359. require.Equal(t, a, dial)
  360. require.NoError(t, peerManager.DialFailed(dial))
  361. failed := time.Now()
  362. // The retry timer should unblock DialNext and make a available again after
  363. // the retry time passes.
  364. ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
  365. defer cancel()
  366. dial, err = peerManager.DialNext(ctx)
  367. require.NoError(t, err)
  368. require.Equal(t, a, dial)
  369. require.GreaterOrEqual(t, time.Since(failed), options.MinRetryTime)
  370. }
  371. func TestPeerManager_DialNext_WakeOnDisconnected(t *testing.T) {
  372. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  373. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{})
  374. require.NoError(t, err)
  375. added, err := peerManager.Add(a)
  376. require.NoError(t, err)
  377. require.True(t, added)
  378. err = peerManager.Accepted(a.NodeID)
  379. require.NoError(t, err)
  380. dial, err := peerManager.TryDialNext()
  381. require.NoError(t, err)
  382. require.Zero(t, dial)
  383. go func() {
  384. time.Sleep(200 * time.Millisecond)
  385. peerManager.Disconnected(a.NodeID)
  386. }()
  387. ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
  388. defer cancel()
  389. dial, err = peerManager.DialNext(ctx)
  390. require.NoError(t, err)
  391. require.Equal(t, a, dial)
  392. }
  393. func TestPeerManager_TryDialNext_MaxConnected(t *testing.T) {
  394. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  395. b := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("b", 40))}
  396. c := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("c", 40))}
  397. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{
  398. MaxConnected: 2,
  399. })
  400. require.NoError(t, err)
  401. // Add a and connect to it.
  402. added, err := peerManager.Add(a)
  403. require.NoError(t, err)
  404. require.True(t, added)
  405. dial, err := peerManager.TryDialNext()
  406. require.NoError(t, err)
  407. require.Equal(t, a, dial)
  408. require.NoError(t, peerManager.Dialed(a))
  409. // Add b and start dialing it.
  410. added, err = peerManager.Add(b)
  411. require.NoError(t, err)
  412. require.True(t, added)
  413. dial, err = peerManager.TryDialNext()
  414. require.NoError(t, err)
  415. require.Equal(t, b, dial)
  416. // At this point, adding c will not allow dialing it.
  417. added, err = peerManager.Add(c)
  418. require.NoError(t, err)
  419. require.True(t, added)
  420. dial, err = peerManager.TryDialNext()
  421. require.NoError(t, err)
  422. require.Zero(t, dial)
  423. }
  424. func TestPeerManager_TryDialNext_MaxConnectedUpgrade(t *testing.T) {
  425. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  426. b := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("b", 40))}
  427. c := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("c", 40))}
  428. d := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("d", 40))}
  429. e := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("e", 40))}
  430. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{
  431. PeerScores: map[types.NodeID]p2p.PeerScore{
  432. a.NodeID: 0,
  433. b.NodeID: 1,
  434. c.NodeID: 2,
  435. d.NodeID: 3,
  436. e.NodeID: 0,
  437. },
  438. PersistentPeers: []types.NodeID{c.NodeID, d.NodeID},
  439. MaxConnected: 2,
  440. MaxConnectedUpgrade: 1,
  441. })
  442. require.NoError(t, err)
  443. // Add a and connect to it.
  444. added, err := peerManager.Add(a)
  445. require.NoError(t, err)
  446. require.True(t, added)
  447. dial, err := peerManager.TryDialNext()
  448. require.NoError(t, err)
  449. require.Equal(t, a, dial)
  450. require.NoError(t, peerManager.Dialed(a))
  451. // Add b and start dialing it.
  452. added, err = peerManager.Add(b)
  453. require.NoError(t, err)
  454. require.True(t, added)
  455. dial, err = peerManager.TryDialNext()
  456. require.NoError(t, err)
  457. require.Equal(t, b, dial)
  458. // Even though we are at capacity, we should be allowed to dial c for an
  459. // upgrade of a, since it's higher-scored.
  460. added, err = peerManager.Add(c)
  461. require.NoError(t, err)
  462. require.True(t, added)
  463. dial, err = peerManager.TryDialNext()
  464. require.NoError(t, err)
  465. require.Equal(t, c, dial)
  466. // However, since we're using all upgrade slots now, we can't add and dial
  467. // d, even though it's also higher-scored.
  468. added, err = peerManager.Add(d)
  469. require.NoError(t, err)
  470. require.True(t, added)
  471. dial, err = peerManager.TryDialNext()
  472. require.NoError(t, err)
  473. require.Zero(t, dial)
  474. // We go through with c's upgrade.
  475. require.NoError(t, peerManager.Dialed(c))
  476. // Still can't dial d.
  477. dial, err = peerManager.TryDialNext()
  478. require.NoError(t, err)
  479. require.Zero(t, dial)
  480. // Now, if we disconnect a, we should be allowed to dial d because we have a
  481. // free upgrade slot.
  482. peerManager.Disconnected(a.NodeID)
  483. dial, err = peerManager.TryDialNext()
  484. require.NoError(t, err)
  485. require.Equal(t, d, dial)
  486. require.NoError(t, peerManager.Dialed(d))
  487. // However, if we disconnect b (such that only c and d are connected), we
  488. // should not be allowed to dial e even though there are upgrade slots,
  489. // because there are no lower-scored nodes that can be upgraded.
  490. peerManager.Disconnected(b.NodeID)
  491. added, err = peerManager.Add(e)
  492. require.NoError(t, err)
  493. require.True(t, added)
  494. dial, err = peerManager.TryDialNext()
  495. require.NoError(t, err)
  496. require.Zero(t, dial)
  497. }
  498. func TestPeerManager_TryDialNext_UpgradeReservesPeer(t *testing.T) {
  499. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  500. b := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("b", 40))}
  501. c := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("c", 40))}
  502. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{
  503. PeerScores: map[types.NodeID]p2p.PeerScore{b.NodeID: 1, c.NodeID: 1},
  504. MaxConnected: 1,
  505. MaxConnectedUpgrade: 2,
  506. })
  507. require.NoError(t, err)
  508. // Add a and connect to it.
  509. added, err := peerManager.Add(a)
  510. require.NoError(t, err)
  511. require.True(t, added)
  512. dial, err := peerManager.TryDialNext()
  513. require.NoError(t, err)
  514. require.Equal(t, a, dial)
  515. require.NoError(t, peerManager.Dialed(a))
  516. // Add b and start dialing it. This will claim a for upgrading.
  517. added, err = peerManager.Add(b)
  518. require.NoError(t, err)
  519. require.True(t, added)
  520. dial, err = peerManager.TryDialNext()
  521. require.NoError(t, err)
  522. require.Equal(t, b, dial)
  523. // Adding c and dialing it will fail, because a is the only connected
  524. // peer that can be upgraded, and b is already trying to upgrade it.
  525. added, err = peerManager.Add(c)
  526. require.NoError(t, err)
  527. require.True(t, added)
  528. dial, err = peerManager.TryDialNext()
  529. require.NoError(t, err)
  530. require.Empty(t, dial)
  531. }
  532. func TestPeerManager_TryDialNext_DialingConnected(t *testing.T) {
  533. aID := types.NodeID(strings.Repeat("a", 40))
  534. a := p2p.NodeAddress{Protocol: "memory", NodeID: aID}
  535. aTCP := p2p.NodeAddress{Protocol: "tcp", NodeID: aID, Hostname: "localhost"}
  536. bID := types.NodeID(strings.Repeat("b", 40))
  537. b := p2p.NodeAddress{Protocol: "memory", NodeID: bID}
  538. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{
  539. MaxConnected: 2,
  540. })
  541. require.NoError(t, err)
  542. // Add a and dial it.
  543. added, err := peerManager.Add(a)
  544. require.NoError(t, err)
  545. require.True(t, added)
  546. dial, err := peerManager.TryDialNext()
  547. require.NoError(t, err)
  548. require.Equal(t, a, dial)
  549. // Adding a's TCP address will not dispense a, since it's already dialing.
  550. added, err = peerManager.Add(aTCP)
  551. require.NoError(t, err)
  552. require.True(t, added)
  553. dial, err = peerManager.TryDialNext()
  554. require.NoError(t, err)
  555. require.Zero(t, dial)
  556. // Marking a as dialed will still not dispense it.
  557. require.NoError(t, peerManager.Dialed(a))
  558. dial, err = peerManager.TryDialNext()
  559. require.NoError(t, err)
  560. require.Zero(t, dial)
  561. // Adding b and accepting a connection from it will not dispense it either.
  562. added, err = peerManager.Add(b)
  563. require.NoError(t, err)
  564. require.True(t, added)
  565. require.NoError(t, peerManager.Accepted(bID))
  566. dial, err = peerManager.TryDialNext()
  567. require.NoError(t, err)
  568. require.Zero(t, dial)
  569. }
  570. func TestPeerManager_TryDialNext_Multiple(t *testing.T) {
  571. aID := types.NodeID(strings.Repeat("a", 40))
  572. bID := types.NodeID(strings.Repeat("b", 40))
  573. addresses := []p2p.NodeAddress{
  574. {Protocol: "memory", NodeID: aID},
  575. {Protocol: "memory", NodeID: bID},
  576. {Protocol: "tcp", NodeID: aID, Hostname: "127.0.0.1"},
  577. {Protocol: "tcp", NodeID: bID, Hostname: "::1"},
  578. }
  579. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{})
  580. require.NoError(t, err)
  581. for _, address := range addresses {
  582. added, err := peerManager.Add(address)
  583. require.NoError(t, err)
  584. require.True(t, added)
  585. }
  586. // All addresses should be dispensed as long as dialing them has failed.
  587. dial := []p2p.NodeAddress{}
  588. for range addresses {
  589. address, err := peerManager.TryDialNext()
  590. require.NoError(t, err)
  591. require.NotZero(t, address)
  592. require.NoError(t, peerManager.DialFailed(address))
  593. dial = append(dial, address)
  594. }
  595. require.ElementsMatch(t, dial, addresses)
  596. address, err := peerManager.TryDialNext()
  597. require.NoError(t, err)
  598. require.Zero(t, address)
  599. }
  600. func TestPeerManager_DialFailed(t *testing.T) {
  601. // DialFailed is tested through other tests, we'll just check a few basic
  602. // things here, e.g. reporting unknown addresses.
  603. aID := types.NodeID(strings.Repeat("a", 40))
  604. a := p2p.NodeAddress{Protocol: "memory", NodeID: aID}
  605. bID := types.NodeID(strings.Repeat("b", 40))
  606. b := p2p.NodeAddress{Protocol: "memory", NodeID: bID}
  607. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{})
  608. require.NoError(t, err)
  609. added, err := peerManager.Add(a)
  610. require.NoError(t, err)
  611. require.True(t, added)
  612. // Dialing and then calling DialFailed with a different address (same
  613. // NodeID) should unmark as dialing and allow us to dial the other address
  614. // again, but not register the failed address.
  615. dial, err := peerManager.TryDialNext()
  616. require.NoError(t, err)
  617. require.Equal(t, a, dial)
  618. require.NoError(t, peerManager.DialFailed(p2p.NodeAddress{
  619. Protocol: "tcp", NodeID: aID, Hostname: "localhost"}))
  620. require.Equal(t, []p2p.NodeAddress{a}, peerManager.Addresses(aID))
  621. dial, err = peerManager.TryDialNext()
  622. require.NoError(t, err)
  623. require.Equal(t, a, dial)
  624. // Calling DialFailed on same address twice should be fine.
  625. require.NoError(t, peerManager.DialFailed(a))
  626. require.NoError(t, peerManager.DialFailed(a))
  627. // DialFailed on an unknown peer shouldn't error or add it.
  628. require.NoError(t, peerManager.DialFailed(b))
  629. require.Equal(t, []types.NodeID{aID}, peerManager.Peers())
  630. }
  631. func TestPeerManager_DialFailed_UnreservePeer(t *testing.T) {
  632. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  633. b := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("b", 40))}
  634. c := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("c", 40))}
  635. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{
  636. PeerScores: map[types.NodeID]p2p.PeerScore{b.NodeID: 1, c.NodeID: 1},
  637. MaxConnected: 1,
  638. MaxConnectedUpgrade: 2,
  639. })
  640. require.NoError(t, err)
  641. // Add a and connect to it.
  642. added, err := peerManager.Add(a)
  643. require.NoError(t, err)
  644. require.True(t, added)
  645. dial, err := peerManager.TryDialNext()
  646. require.NoError(t, err)
  647. require.Equal(t, a, dial)
  648. require.NoError(t, peerManager.Dialed(a))
  649. // Add b and start dialing it. This will claim a for upgrading.
  650. added, err = peerManager.Add(b)
  651. require.NoError(t, err)
  652. require.True(t, added)
  653. dial, err = peerManager.TryDialNext()
  654. require.NoError(t, err)
  655. require.Equal(t, b, dial)
  656. // Adding c and dialing it will fail, even though it could upgrade a and we
  657. // have free upgrade slots, because a is the only connected peer that can be
  658. // upgraded and b is already trying to upgrade it.
  659. added, err = peerManager.Add(c)
  660. require.NoError(t, err)
  661. require.True(t, added)
  662. dial, err = peerManager.TryDialNext()
  663. require.NoError(t, err)
  664. require.Empty(t, dial)
  665. // Failing b's dial will now make c available for dialing.
  666. require.NoError(t, peerManager.DialFailed(b))
  667. dial, err = peerManager.TryDialNext()
  668. require.NoError(t, err)
  669. require.Equal(t, c, dial)
  670. }
  671. func TestPeerManager_Dialed_Connected(t *testing.T) {
  672. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  673. b := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("b", 40))}
  674. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{})
  675. require.NoError(t, err)
  676. // Marking a as dialed twice should error.
  677. added, err := peerManager.Add(a)
  678. require.NoError(t, err)
  679. require.True(t, added)
  680. dial, err := peerManager.TryDialNext()
  681. require.NoError(t, err)
  682. require.Equal(t, a, dial)
  683. require.NoError(t, peerManager.Dialed(a))
  684. require.Error(t, peerManager.Dialed(a))
  685. // Accepting a connection from b and then trying to mark it as dialed should fail.
  686. added, err = peerManager.Add(b)
  687. require.NoError(t, err)
  688. require.True(t, added)
  689. dial, err = peerManager.TryDialNext()
  690. require.NoError(t, err)
  691. require.Equal(t, b, dial)
  692. require.NoError(t, peerManager.Accepted(b.NodeID))
  693. require.Error(t, peerManager.Dialed(b))
  694. }
  695. func TestPeerManager_Dialed_Self(t *testing.T) {
  696. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{})
  697. require.NoError(t, err)
  698. // Dialing self should error.
  699. _, err = peerManager.Add(p2p.NodeAddress{Protocol: "memory", NodeID: selfID})
  700. require.Error(t, err)
  701. }
  702. func TestPeerManager_Dialed_MaxConnected(t *testing.T) {
  703. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  704. b := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("b", 40))}
  705. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{
  706. MaxConnected: 1,
  707. })
  708. require.NoError(t, err)
  709. // Start to dial a.
  710. added, err := peerManager.Add(a)
  711. require.NoError(t, err)
  712. require.True(t, added)
  713. dial, err := peerManager.TryDialNext()
  714. require.NoError(t, err)
  715. require.Equal(t, a, dial)
  716. // Marking b as dialed in the meanwhile (even without TryDialNext)
  717. // should be fine.
  718. added, err = peerManager.Add(b)
  719. require.NoError(t, err)
  720. require.True(t, added)
  721. require.NoError(t, peerManager.Dialed(b))
  722. // Completing the dial for a should now error.
  723. require.Error(t, peerManager.Dialed(a))
  724. }
  725. func TestPeerManager_Dialed_MaxConnectedUpgrade(t *testing.T) {
  726. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  727. b := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("b", 40))}
  728. c := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("c", 40))}
  729. d := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("d", 40))}
  730. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{
  731. MaxConnected: 2,
  732. MaxConnectedUpgrade: 1,
  733. PeerScores: map[types.NodeID]p2p.PeerScore{c.NodeID: 1, d.NodeID: 1},
  734. })
  735. require.NoError(t, err)
  736. // Dialing a and b is fine.
  737. added, err := peerManager.Add(a)
  738. require.NoError(t, err)
  739. require.True(t, added)
  740. require.NoError(t, peerManager.Dialed(a))
  741. added, err = peerManager.Add(b)
  742. require.NoError(t, err)
  743. require.True(t, added)
  744. require.NoError(t, peerManager.Dialed(b))
  745. // Starting an upgrade of c should be fine.
  746. added, err = peerManager.Add(c)
  747. require.NoError(t, err)
  748. require.True(t, added)
  749. dial, err := peerManager.TryDialNext()
  750. require.NoError(t, err)
  751. require.Equal(t, c, dial)
  752. require.NoError(t, peerManager.Dialed(c))
  753. // Trying to mark d dialed should fail, since there are no more upgrade
  754. // slots and a/b haven't been evicted yet.
  755. added, err = peerManager.Add(d)
  756. require.NoError(t, err)
  757. require.True(t, added)
  758. require.Error(t, peerManager.Dialed(d))
  759. }
  760. func TestPeerManager_Dialed_Unknown(t *testing.T) {
  761. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  762. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{})
  763. require.NoError(t, err)
  764. // Marking an unknown node as dialed should error.
  765. require.Error(t, peerManager.Dialed(a))
  766. }
  767. func TestPeerManager_Dialed_Upgrade(t *testing.T) {
  768. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  769. b := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("b", 40))}
  770. c := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("c", 40))}
  771. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{
  772. MaxConnected: 1,
  773. MaxConnectedUpgrade: 2,
  774. PeerScores: map[types.NodeID]p2p.PeerScore{b.NodeID: 1, c.NodeID: 1},
  775. })
  776. require.NoError(t, err)
  777. // Dialing a is fine.
  778. added, err := peerManager.Add(a)
  779. require.NoError(t, err)
  780. require.True(t, added)
  781. require.NoError(t, peerManager.Dialed(a))
  782. // Upgrading it with b should work, since b has a higher score.
  783. added, err = peerManager.Add(b)
  784. require.NoError(t, err)
  785. require.True(t, added)
  786. dial, err := peerManager.TryDialNext()
  787. require.NoError(t, err)
  788. require.Equal(t, b, dial)
  789. require.NoError(t, peerManager.Dialed(b))
  790. // a hasn't been evicted yet, but c shouldn't be allowed to upgrade anyway
  791. // since it's about to be evicted.
  792. added, err = peerManager.Add(c)
  793. require.NoError(t, err)
  794. require.True(t, added)
  795. dial, err = peerManager.TryDialNext()
  796. require.NoError(t, err)
  797. require.Empty(t, dial)
  798. // a should now be evicted.
  799. evict, err := peerManager.TryEvictNext()
  800. require.NoError(t, err)
  801. require.Equal(t, a.NodeID, evict)
  802. }
  803. func TestPeerManager_Dialed_UpgradeEvenLower(t *testing.T) {
  804. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  805. b := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("b", 40))}
  806. c := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("c", 40))}
  807. d := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("d", 40))}
  808. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{
  809. MaxConnected: 2,
  810. MaxConnectedUpgrade: 1,
  811. PeerScores: map[types.NodeID]p2p.PeerScore{
  812. a.NodeID: 3,
  813. b.NodeID: 2,
  814. c.NodeID: 10,
  815. d.NodeID: 1,
  816. },
  817. })
  818. require.NoError(t, err)
  819. // Connect to a and b.
  820. added, err := peerManager.Add(a)
  821. require.NoError(t, err)
  822. require.True(t, added)
  823. require.NoError(t, peerManager.Dialed(a))
  824. added, err = peerManager.Add(b)
  825. require.NoError(t, err)
  826. require.True(t, added)
  827. require.NoError(t, peerManager.Dialed(b))
  828. // Start an upgrade with c, which should pick b to upgrade (since it
  829. // has score 2).
  830. added, err = peerManager.Add(c)
  831. require.NoError(t, err)
  832. require.True(t, added)
  833. dial, err := peerManager.TryDialNext()
  834. require.NoError(t, err)
  835. require.Equal(t, c, dial)
  836. // In the meanwhile, a disconnects and d connects. d is even lower-scored
  837. // than b (1 vs 2), which is currently being upgraded.
  838. peerManager.Disconnected(a.NodeID)
  839. added, err = peerManager.Add(d)
  840. require.NoError(t, err)
  841. require.True(t, added)
  842. require.NoError(t, peerManager.Accepted(d.NodeID))
  843. // Once c completes the upgrade of b, it should instead evict d,
  844. // since it has en even lower score.
  845. require.NoError(t, peerManager.Dialed(c))
  846. evict, err := peerManager.TryEvictNext()
  847. require.NoError(t, err)
  848. require.Equal(t, d.NodeID, evict)
  849. }
  850. func TestPeerManager_Dialed_UpgradeNoEvict(t *testing.T) {
  851. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  852. b := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("b", 40))}
  853. c := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("c", 40))}
  854. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{
  855. MaxConnected: 2,
  856. MaxConnectedUpgrade: 1,
  857. PeerScores: map[types.NodeID]p2p.PeerScore{
  858. a.NodeID: 1,
  859. b.NodeID: 2,
  860. c.NodeID: 3,
  861. },
  862. })
  863. require.NoError(t, err)
  864. // Connect to a and b.
  865. added, err := peerManager.Add(a)
  866. require.NoError(t, err)
  867. require.True(t, added)
  868. require.NoError(t, peerManager.Dialed(a))
  869. added, err = peerManager.Add(b)
  870. require.NoError(t, err)
  871. require.True(t, added)
  872. require.NoError(t, peerManager.Dialed(b))
  873. // Start an upgrade with c, which should pick a to upgrade.
  874. added, err = peerManager.Add(c)
  875. require.NoError(t, err)
  876. require.True(t, added)
  877. dial, err := peerManager.TryDialNext()
  878. require.NoError(t, err)
  879. require.Equal(t, c, dial)
  880. // In the meanwhile, b disconnects.
  881. peerManager.Disconnected(b.NodeID)
  882. // Once c completes the upgrade of b, there is no longer a need to
  883. // evict anything since we're at capacity.
  884. // since it has en even lower score.
  885. require.NoError(t, peerManager.Dialed(c))
  886. evict, err := peerManager.TryEvictNext()
  887. require.NoError(t, err)
  888. require.Zero(t, evict)
  889. }
  890. func TestPeerManager_Accepted(t *testing.T) {
  891. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  892. b := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("b", 40))}
  893. c := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("c", 40))}
  894. d := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("d", 40))}
  895. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{})
  896. require.NoError(t, err)
  897. // Accepting a connection from self should error.
  898. require.Error(t, peerManager.Accepted(selfID))
  899. // Accepting a connection from a known peer should work.
  900. added, err := peerManager.Add(a)
  901. require.NoError(t, err)
  902. require.True(t, added)
  903. require.NoError(t, peerManager.Accepted(a.NodeID))
  904. // Accepting a connection from an already accepted peer should error.
  905. require.Error(t, peerManager.Accepted(a.NodeID))
  906. // Accepting a connection from an unknown peer should work and register it.
  907. require.NoError(t, peerManager.Accepted(b.NodeID))
  908. require.ElementsMatch(t, []types.NodeID{a.NodeID, b.NodeID}, peerManager.Peers())
  909. // Accepting a connection from a peer that's being dialed should work, and
  910. // should cause the dial to fail.
  911. added, err = peerManager.Add(c)
  912. require.NoError(t, err)
  913. require.True(t, added)
  914. dial, err := peerManager.TryDialNext()
  915. require.NoError(t, err)
  916. require.Equal(t, c, dial)
  917. require.NoError(t, peerManager.Accepted(c.NodeID))
  918. require.Error(t, peerManager.Dialed(c))
  919. // Accepting a connection from a peer that's been dialed should fail.
  920. added, err = peerManager.Add(d)
  921. require.NoError(t, err)
  922. require.True(t, added)
  923. dial, err = peerManager.TryDialNext()
  924. require.NoError(t, err)
  925. require.Equal(t, d, dial)
  926. require.NoError(t, peerManager.Dialed(d))
  927. require.Error(t, peerManager.Accepted(d.NodeID))
  928. }
  929. func TestPeerManager_Accepted_MaxConnected(t *testing.T) {
  930. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  931. b := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("b", 40))}
  932. c := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("c", 40))}
  933. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{
  934. MaxConnected: 2,
  935. })
  936. require.NoError(t, err)
  937. // Connect to a and b.
  938. added, err := peerManager.Add(a)
  939. require.NoError(t, err)
  940. require.True(t, added)
  941. require.NoError(t, peerManager.Dialed(a))
  942. added, err = peerManager.Add(b)
  943. require.NoError(t, err)
  944. require.True(t, added)
  945. require.NoError(t, peerManager.Accepted(b.NodeID))
  946. // Accepting c should now fail.
  947. added, err = peerManager.Add(c)
  948. require.NoError(t, err)
  949. require.True(t, added)
  950. require.Error(t, peerManager.Accepted(c.NodeID))
  951. }
  952. func TestPeerManager_Accepted_MaxConnectedUpgrade(t *testing.T) {
  953. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  954. b := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("b", 40))}
  955. c := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("c", 40))}
  956. d := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("d", 40))}
  957. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{
  958. PeerScores: map[types.NodeID]p2p.PeerScore{
  959. c.NodeID: 1,
  960. d.NodeID: 2,
  961. },
  962. MaxConnected: 1,
  963. MaxConnectedUpgrade: 1,
  964. })
  965. require.NoError(t, err)
  966. // Dial a.
  967. added, err := peerManager.Add(a)
  968. require.NoError(t, err)
  969. require.True(t, added)
  970. require.NoError(t, peerManager.Dialed(a))
  971. // Accepting b should fail, since it's not an upgrade over a.
  972. added, err = peerManager.Add(b)
  973. require.NoError(t, err)
  974. require.True(t, added)
  975. require.Error(t, peerManager.Accepted(b.NodeID))
  976. // Accepting c should work, since it upgrades a.
  977. added, err = peerManager.Add(c)
  978. require.NoError(t, err)
  979. require.True(t, added)
  980. require.NoError(t, peerManager.Accepted(c.NodeID))
  981. // a still hasn't been evicted, so accepting b should still fail.
  982. _, err = peerManager.Add(b)
  983. require.NoError(t, err)
  984. require.Error(t, peerManager.Accepted(b.NodeID))
  985. // Also, accepting d should fail, since all upgrade slots are full.
  986. added, err = peerManager.Add(d)
  987. require.NoError(t, err)
  988. require.True(t, added)
  989. require.Error(t, peerManager.Accepted(d.NodeID))
  990. }
  991. func TestPeerManager_Accepted_Upgrade(t *testing.T) {
  992. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  993. b := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("b", 40))}
  994. c := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("c", 40))}
  995. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{
  996. PeerScores: map[types.NodeID]p2p.PeerScore{
  997. b.NodeID: 1,
  998. c.NodeID: 1,
  999. },
  1000. MaxConnected: 1,
  1001. MaxConnectedUpgrade: 2,
  1002. })
  1003. require.NoError(t, err)
  1004. // Accept a.
  1005. added, err := peerManager.Add(a)
  1006. require.NoError(t, err)
  1007. require.True(t, added)
  1008. require.NoError(t, peerManager.Accepted(a.NodeID))
  1009. // Accepting b should work, since it upgrades a.
  1010. added, err = peerManager.Add(b)
  1011. require.NoError(t, err)
  1012. require.True(t, added)
  1013. require.NoError(t, peerManager.Accepted(b.NodeID))
  1014. // c cannot get accepted, since a has been upgraded by b.
  1015. added, err = peerManager.Add(c)
  1016. require.NoError(t, err)
  1017. require.True(t, added)
  1018. require.Error(t, peerManager.Accepted(c.NodeID))
  1019. // This should cause a to get evicted.
  1020. evict, err := peerManager.TryEvictNext()
  1021. require.NoError(t, err)
  1022. require.Equal(t, a.NodeID, evict)
  1023. peerManager.Disconnected(a.NodeID)
  1024. // c still cannot get accepted, since it's not scored above b.
  1025. require.Error(t, peerManager.Accepted(c.NodeID))
  1026. }
  1027. func TestPeerManager_Accepted_UpgradeDialing(t *testing.T) {
  1028. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  1029. b := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("b", 40))}
  1030. c := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("c", 40))}
  1031. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{
  1032. PeerScores: map[types.NodeID]p2p.PeerScore{
  1033. b.NodeID: 1,
  1034. c.NodeID: 1,
  1035. },
  1036. MaxConnected: 1,
  1037. MaxConnectedUpgrade: 2,
  1038. })
  1039. require.NoError(t, err)
  1040. // Accept a.
  1041. added, err := peerManager.Add(a)
  1042. require.NoError(t, err)
  1043. require.True(t, added)
  1044. require.NoError(t, peerManager.Accepted(a.NodeID))
  1045. // Start dial upgrade from a to b.
  1046. added, err = peerManager.Add(b)
  1047. require.NoError(t, err)
  1048. require.True(t, added)
  1049. dial, err := peerManager.TryDialNext()
  1050. require.NoError(t, err)
  1051. require.Equal(t, b, dial)
  1052. // a has already been claimed as an upgrade of a, so accepting
  1053. // c should fail since there's noone else to upgrade.
  1054. added, err = peerManager.Add(c)
  1055. require.NoError(t, err)
  1056. require.True(t, added)
  1057. require.Error(t, peerManager.Accepted(c.NodeID))
  1058. // However, if b connects to us while we're also trying to upgrade to it via
  1059. // dialing, then we accept the incoming connection as an upgrade.
  1060. require.NoError(t, peerManager.Accepted(b.NodeID))
  1061. // This should cause a to get evicted, and the dial upgrade to fail.
  1062. evict, err := peerManager.TryEvictNext()
  1063. require.NoError(t, err)
  1064. require.Equal(t, a.NodeID, evict)
  1065. require.Error(t, peerManager.Dialed(b))
  1066. }
  1067. func TestPeerManager_Ready(t *testing.T) {
  1068. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  1069. b := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("b", 40))}
  1070. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{})
  1071. require.NoError(t, err)
  1072. sub := peerManager.Subscribe()
  1073. defer sub.Close()
  1074. // Connecting to a should still have it as status down.
  1075. added, err := peerManager.Add(a)
  1076. require.NoError(t, err)
  1077. require.True(t, added)
  1078. require.NoError(t, peerManager.Accepted(a.NodeID))
  1079. require.Equal(t, p2p.PeerStatusDown, peerManager.Status(a.NodeID))
  1080. // Marking a as ready should transition it to PeerStatusUp and send an update.
  1081. peerManager.Ready(a.NodeID)
  1082. require.Equal(t, p2p.PeerStatusUp, peerManager.Status(a.NodeID))
  1083. require.Equal(t, p2p.PeerUpdate{
  1084. NodeID: a.NodeID,
  1085. Status: p2p.PeerStatusUp,
  1086. }, <-sub.Updates())
  1087. // Marking an unconnected peer as ready should do nothing.
  1088. added, err = peerManager.Add(b)
  1089. require.NoError(t, err)
  1090. require.True(t, added)
  1091. require.Equal(t, p2p.PeerStatusDown, peerManager.Status(b.NodeID))
  1092. peerManager.Ready(b.NodeID)
  1093. require.Equal(t, p2p.PeerStatusDown, peerManager.Status(b.NodeID))
  1094. require.Empty(t, sub.Updates())
  1095. }
  1096. // See TryEvictNext for most tests, this just tests blocking behavior.
  1097. func TestPeerManager_EvictNext(t *testing.T) {
  1098. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  1099. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{})
  1100. require.NoError(t, err)
  1101. added, err := peerManager.Add(a)
  1102. require.NoError(t, err)
  1103. require.True(t, added)
  1104. require.NoError(t, peerManager.Accepted(a.NodeID))
  1105. peerManager.Ready(a.NodeID)
  1106. // Since there are no peers to evict, EvictNext should block until timeout.
  1107. timeoutCtx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
  1108. defer cancel()
  1109. _, err = peerManager.EvictNext(timeoutCtx)
  1110. require.Error(t, err)
  1111. require.Equal(t, context.DeadlineExceeded, err)
  1112. // Erroring the peer will return it from EvictNext().
  1113. peerManager.Errored(a.NodeID, errors.New("foo"))
  1114. evict, err := peerManager.EvictNext(timeoutCtx)
  1115. require.NoError(t, err)
  1116. require.Equal(t, a.NodeID, evict)
  1117. // Since there are no more peers to evict, the next call should block.
  1118. timeoutCtx, cancel = context.WithTimeout(ctx, 100*time.Millisecond)
  1119. defer cancel()
  1120. _, err = peerManager.EvictNext(timeoutCtx)
  1121. require.Error(t, err)
  1122. require.Equal(t, context.DeadlineExceeded, err)
  1123. }
  1124. func TestPeerManager_EvictNext_WakeOnError(t *testing.T) {
  1125. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  1126. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{})
  1127. require.NoError(t, err)
  1128. added, err := peerManager.Add(a)
  1129. require.NoError(t, err)
  1130. require.True(t, added)
  1131. require.NoError(t, peerManager.Accepted(a.NodeID))
  1132. peerManager.Ready(a.NodeID)
  1133. // Spawn a goroutine to error a peer after a delay.
  1134. go func() {
  1135. time.Sleep(200 * time.Millisecond)
  1136. peerManager.Errored(a.NodeID, errors.New("foo"))
  1137. }()
  1138. // This will block until peer errors above.
  1139. ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
  1140. defer cancel()
  1141. evict, err := peerManager.EvictNext(ctx)
  1142. require.NoError(t, err)
  1143. require.Equal(t, a.NodeID, evict)
  1144. }
  1145. func TestPeerManager_EvictNext_WakeOnUpgradeDialed(t *testing.T) {
  1146. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  1147. b := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("b", 40))}
  1148. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{
  1149. MaxConnected: 1,
  1150. MaxConnectedUpgrade: 1,
  1151. PeerScores: map[types.NodeID]p2p.PeerScore{b.NodeID: 1},
  1152. })
  1153. require.NoError(t, err)
  1154. // Connect a.
  1155. added, err := peerManager.Add(a)
  1156. require.NoError(t, err)
  1157. require.True(t, added)
  1158. require.NoError(t, peerManager.Accepted(a.NodeID))
  1159. peerManager.Ready(a.NodeID)
  1160. // Spawn a goroutine to upgrade to b with a delay.
  1161. go func() {
  1162. time.Sleep(200 * time.Millisecond)
  1163. added, err := peerManager.Add(b)
  1164. require.NoError(t, err)
  1165. require.True(t, added)
  1166. dial, err := peerManager.TryDialNext()
  1167. require.NoError(t, err)
  1168. require.Equal(t, b, dial)
  1169. require.NoError(t, peerManager.Dialed(b))
  1170. }()
  1171. // This will block until peer is upgraded above.
  1172. ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
  1173. defer cancel()
  1174. evict, err := peerManager.EvictNext(ctx)
  1175. require.NoError(t, err)
  1176. require.Equal(t, a.NodeID, evict)
  1177. }
  1178. func TestPeerManager_EvictNext_WakeOnUpgradeAccepted(t *testing.T) {
  1179. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  1180. b := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("b", 40))}
  1181. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{
  1182. MaxConnected: 1,
  1183. MaxConnectedUpgrade: 1,
  1184. PeerScores: map[types.NodeID]p2p.PeerScore{b.NodeID: 1},
  1185. })
  1186. require.NoError(t, err)
  1187. // Connect a.
  1188. added, err := peerManager.Add(a)
  1189. require.NoError(t, err)
  1190. require.True(t, added)
  1191. require.NoError(t, peerManager.Accepted(a.NodeID))
  1192. peerManager.Ready(a.NodeID)
  1193. // Spawn a goroutine to upgrade b with a delay.
  1194. go func() {
  1195. time.Sleep(200 * time.Millisecond)
  1196. require.NoError(t, peerManager.Accepted(b.NodeID))
  1197. }()
  1198. // This will block until peer is upgraded above.
  1199. ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
  1200. defer cancel()
  1201. evict, err := peerManager.EvictNext(ctx)
  1202. require.NoError(t, err)
  1203. require.Equal(t, a.NodeID, evict)
  1204. }
  1205. func TestPeerManager_TryEvictNext(t *testing.T) {
  1206. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  1207. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{})
  1208. require.NoError(t, err)
  1209. added, err := peerManager.Add(a)
  1210. require.NoError(t, err)
  1211. require.True(t, added)
  1212. // Nothing is evicted with no peers connected.
  1213. evict, err := peerManager.TryEvictNext()
  1214. require.NoError(t, err)
  1215. require.Zero(t, evict)
  1216. // Connecting to a won't evict anything either.
  1217. require.NoError(t, peerManager.Accepted(a.NodeID))
  1218. peerManager.Ready(a.NodeID)
  1219. // But if a errors it should be evicted.
  1220. peerManager.Errored(a.NodeID, errors.New("foo"))
  1221. evict, err = peerManager.TryEvictNext()
  1222. require.NoError(t, err)
  1223. require.Equal(t, a.NodeID, evict)
  1224. // While a is being evicted (before disconnect), it shouldn't get evicted again.
  1225. evict, err = peerManager.TryEvictNext()
  1226. require.NoError(t, err)
  1227. require.Zero(t, evict)
  1228. peerManager.Errored(a.NodeID, errors.New("foo"))
  1229. evict, err = peerManager.TryEvictNext()
  1230. require.NoError(t, err)
  1231. require.Zero(t, evict)
  1232. }
  1233. func TestPeerManager_Disconnected(t *testing.T) {
  1234. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  1235. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{})
  1236. require.NoError(t, err)
  1237. sub := peerManager.Subscribe()
  1238. defer sub.Close()
  1239. // Disconnecting an unknown peer does nothing.
  1240. peerManager.Disconnected(a.NodeID)
  1241. require.Empty(t, peerManager.Peers())
  1242. require.Empty(t, sub.Updates())
  1243. // Disconnecting an accepted non-ready peer does not send a status update.
  1244. added, err := peerManager.Add(a)
  1245. require.NoError(t, err)
  1246. require.True(t, added)
  1247. require.NoError(t, peerManager.Accepted(a.NodeID))
  1248. peerManager.Disconnected(a.NodeID)
  1249. require.Empty(t, sub.Updates())
  1250. // Disconnecting a ready peer sends a status update.
  1251. _, err = peerManager.Add(a)
  1252. require.NoError(t, err)
  1253. require.NoError(t, peerManager.Accepted(a.NodeID))
  1254. peerManager.Ready(a.NodeID)
  1255. require.Equal(t, p2p.PeerStatusUp, peerManager.Status(a.NodeID))
  1256. require.NotEmpty(t, sub.Updates())
  1257. require.Equal(t, p2p.PeerUpdate{
  1258. NodeID: a.NodeID,
  1259. Status: p2p.PeerStatusUp,
  1260. }, <-sub.Updates())
  1261. peerManager.Disconnected(a.NodeID)
  1262. require.Equal(t, p2p.PeerStatusDown, peerManager.Status(a.NodeID))
  1263. require.NotEmpty(t, sub.Updates())
  1264. require.Equal(t, p2p.PeerUpdate{
  1265. NodeID: a.NodeID,
  1266. Status: p2p.PeerStatusDown,
  1267. }, <-sub.Updates())
  1268. // Disconnecting a dialing peer does not unmark it as dialing, to avoid
  1269. // dialing it multiple times in parallel.
  1270. dial, err := peerManager.TryDialNext()
  1271. require.NoError(t, err)
  1272. require.Equal(t, a, dial)
  1273. peerManager.Disconnected(a.NodeID)
  1274. dial, err = peerManager.TryDialNext()
  1275. require.NoError(t, err)
  1276. require.Zero(t, dial)
  1277. }
  1278. func TestPeerManager_Errored(t *testing.T) {
  1279. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  1280. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{})
  1281. require.NoError(t, err)
  1282. // Erroring an unknown peer does nothing.
  1283. peerManager.Errored(a.NodeID, errors.New("foo"))
  1284. require.Empty(t, peerManager.Peers())
  1285. evict, err := peerManager.TryEvictNext()
  1286. require.NoError(t, err)
  1287. require.Zero(t, evict)
  1288. // Erroring a known peer does nothing, and won't evict it later,
  1289. // even when it connects.
  1290. added, err := peerManager.Add(a)
  1291. require.NoError(t, err)
  1292. require.True(t, added)
  1293. peerManager.Errored(a.NodeID, errors.New("foo"))
  1294. evict, err = peerManager.TryEvictNext()
  1295. require.NoError(t, err)
  1296. require.Zero(t, evict)
  1297. require.NoError(t, peerManager.Accepted(a.NodeID))
  1298. peerManager.Ready(a.NodeID)
  1299. evict, err = peerManager.TryEvictNext()
  1300. require.NoError(t, err)
  1301. require.Zero(t, evict)
  1302. // However, erroring once connected will evict it.
  1303. peerManager.Errored(a.NodeID, errors.New("foo"))
  1304. evict, err = peerManager.TryEvictNext()
  1305. require.NoError(t, err)
  1306. require.Equal(t, a.NodeID, evict)
  1307. }
  1308. func TestPeerManager_Subscribe(t *testing.T) {
  1309. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  1310. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{})
  1311. require.NoError(t, err)
  1312. // This tests all subscription events for full peer lifecycles.
  1313. sub := peerManager.Subscribe()
  1314. defer sub.Close()
  1315. added, err := peerManager.Add(a)
  1316. require.NoError(t, err)
  1317. require.True(t, added)
  1318. require.Empty(t, sub.Updates())
  1319. // Inbound connection.
  1320. require.NoError(t, peerManager.Accepted(a.NodeID))
  1321. require.Empty(t, sub.Updates())
  1322. peerManager.Ready(a.NodeID)
  1323. require.NotEmpty(t, sub.Updates())
  1324. require.Equal(t, p2p.PeerUpdate{NodeID: a.NodeID, Status: p2p.PeerStatusUp}, <-sub.Updates())
  1325. peerManager.Disconnected(a.NodeID)
  1326. require.NotEmpty(t, sub.Updates())
  1327. require.Equal(t, p2p.PeerUpdate{NodeID: a.NodeID, Status: p2p.PeerStatusDown}, <-sub.Updates())
  1328. // Outbound connection with peer error and eviction.
  1329. dial, err := peerManager.TryDialNext()
  1330. require.NoError(t, err)
  1331. require.Equal(t, a, dial)
  1332. require.Empty(t, sub.Updates())
  1333. require.NoError(t, peerManager.Dialed(a))
  1334. require.Empty(t, sub.Updates())
  1335. peerManager.Ready(a.NodeID)
  1336. require.NotEmpty(t, sub.Updates())
  1337. require.Equal(t, p2p.PeerUpdate{NodeID: a.NodeID, Status: p2p.PeerStatusUp}, <-sub.Updates())
  1338. peerManager.Errored(a.NodeID, errors.New("foo"))
  1339. require.Empty(t, sub.Updates())
  1340. evict, err := peerManager.TryEvictNext()
  1341. require.NoError(t, err)
  1342. require.Equal(t, a.NodeID, evict)
  1343. peerManager.Disconnected(a.NodeID)
  1344. require.NotEmpty(t, sub.Updates())
  1345. require.Equal(t, p2p.PeerUpdate{NodeID: a.NodeID, Status: p2p.PeerStatusDown}, <-sub.Updates())
  1346. // Outbound connection with dial failure.
  1347. dial, err = peerManager.TryDialNext()
  1348. require.NoError(t, err)
  1349. require.Equal(t, a, dial)
  1350. require.Empty(t, sub.Updates())
  1351. require.NoError(t, peerManager.DialFailed(a))
  1352. require.Empty(t, sub.Updates())
  1353. }
  1354. func TestPeerManager_Subscribe_Close(t *testing.T) {
  1355. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  1356. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{})
  1357. require.NoError(t, err)
  1358. sub := peerManager.Subscribe()
  1359. defer sub.Close()
  1360. added, err := peerManager.Add(a)
  1361. require.NoError(t, err)
  1362. require.True(t, added)
  1363. require.NoError(t, peerManager.Accepted(a.NodeID))
  1364. require.Empty(t, sub.Updates())
  1365. peerManager.Ready(a.NodeID)
  1366. require.NotEmpty(t, sub.Updates())
  1367. require.Equal(t, p2p.PeerUpdate{NodeID: a.NodeID, Status: p2p.PeerStatusUp}, <-sub.Updates())
  1368. // Closing the subscription should not send us the disconnected update.
  1369. sub.Close()
  1370. peerManager.Disconnected(a.NodeID)
  1371. require.Empty(t, sub.Updates())
  1372. }
  1373. func TestPeerManager_Subscribe_Broadcast(t *testing.T) {
  1374. t.Cleanup(leaktest.Check(t))
  1375. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  1376. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{})
  1377. require.NoError(t, err)
  1378. s1 := peerManager.Subscribe()
  1379. defer s1.Close()
  1380. s2 := peerManager.Subscribe()
  1381. defer s2.Close()
  1382. s3 := peerManager.Subscribe()
  1383. defer s3.Close()
  1384. // Connecting to a peer should send updates on all subscriptions.
  1385. added, err := peerManager.Add(a)
  1386. require.NoError(t, err)
  1387. require.True(t, added)
  1388. require.NoError(t, peerManager.Accepted(a.NodeID))
  1389. peerManager.Ready(a.NodeID)
  1390. expectUp := p2p.PeerUpdate{NodeID: a.NodeID, Status: p2p.PeerStatusUp}
  1391. require.NotEmpty(t, s1)
  1392. require.Equal(t, expectUp, <-s1.Updates())
  1393. require.NotEmpty(t, s2)
  1394. require.Equal(t, expectUp, <-s2.Updates())
  1395. require.NotEmpty(t, s3)
  1396. require.Equal(t, expectUp, <-s3.Updates())
  1397. // We now close s2. Disconnecting the peer should only send updates
  1398. // on s1 and s3.
  1399. s2.Close()
  1400. peerManager.Disconnected(a.NodeID)
  1401. expectDown := p2p.PeerUpdate{NodeID: a.NodeID, Status: p2p.PeerStatusDown}
  1402. require.NotEmpty(t, s1)
  1403. require.Equal(t, expectDown, <-s1.Updates())
  1404. require.Empty(t, s2.Updates())
  1405. require.NotEmpty(t, s3)
  1406. require.Equal(t, expectDown, <-s3.Updates())
  1407. }
  1408. func TestPeerManager_Close(t *testing.T) {
  1409. // leaktest will check that spawned goroutines are closed.
  1410. t.Cleanup(leaktest.CheckTimeout(t, 1*time.Second))
  1411. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  1412. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{
  1413. MinRetryTime: 10 * time.Second,
  1414. })
  1415. require.NoError(t, err)
  1416. // This subscription isn't closed, but PeerManager.Close()
  1417. // should reap the spawned goroutine.
  1418. _ = peerManager.Subscribe()
  1419. // This dial failure will start a retry timer for 10 seconds, which
  1420. // should be reaped.
  1421. added, err := peerManager.Add(a)
  1422. require.NoError(t, err)
  1423. require.True(t, added)
  1424. dial, err := peerManager.TryDialNext()
  1425. require.NoError(t, err)
  1426. require.Equal(t, a, dial)
  1427. require.NoError(t, peerManager.DialFailed(a))
  1428. // This should clean up the goroutines.
  1429. peerManager.Close()
  1430. }
  1431. func TestPeerManager_Advertise(t *testing.T) {
  1432. aID := types.NodeID(strings.Repeat("a", 40))
  1433. aTCP := p2p.NodeAddress{Protocol: "tcp", NodeID: aID, Hostname: "127.0.0.1", Port: 26657, Path: "/path"}
  1434. aMem := p2p.NodeAddress{Protocol: "memory", NodeID: aID}
  1435. bID := types.NodeID(strings.Repeat("b", 40))
  1436. bTCP := p2p.NodeAddress{Protocol: "tcp", NodeID: bID, Hostname: "b10c::1", Port: 26657, Path: "/path"}
  1437. bMem := p2p.NodeAddress{Protocol: "memory", NodeID: bID}
  1438. cID := types.NodeID(strings.Repeat("c", 40))
  1439. cTCP := p2p.NodeAddress{Protocol: "tcp", NodeID: cID, Hostname: "host.domain", Port: 80}
  1440. cMem := p2p.NodeAddress{Protocol: "memory", NodeID: cID}
  1441. dID := types.NodeID(strings.Repeat("d", 40))
  1442. // Create an initial peer manager and add the peers.
  1443. peerManager, err := p2p.NewPeerManager(selfID, dbm.NewMemDB(), p2p.PeerManagerOptions{
  1444. PeerScores: map[types.NodeID]p2p.PeerScore{aID: 3, bID: 2, cID: 1},
  1445. })
  1446. require.NoError(t, err)
  1447. defer peerManager.Close()
  1448. added, err := peerManager.Add(aTCP)
  1449. require.NoError(t, err)
  1450. require.True(t, added)
  1451. added, err = peerManager.Add(aMem)
  1452. require.NoError(t, err)
  1453. require.True(t, added)
  1454. added, err = peerManager.Add(bTCP)
  1455. require.NoError(t, err)
  1456. require.True(t, added)
  1457. added, err = peerManager.Add(bMem)
  1458. require.NoError(t, err)
  1459. require.True(t, added)
  1460. added, err = peerManager.Add(cTCP)
  1461. require.NoError(t, err)
  1462. require.True(t, added)
  1463. added, err = peerManager.Add(cMem)
  1464. require.NoError(t, err)
  1465. require.True(t, added)
  1466. // d should get all addresses.
  1467. require.ElementsMatch(t, []p2p.NodeAddress{
  1468. aTCP, aMem, bTCP, bMem, cTCP, cMem,
  1469. }, peerManager.Advertise(dID, 100))
  1470. // a should not get its own addresses.
  1471. require.ElementsMatch(t, []p2p.NodeAddress{
  1472. bTCP, bMem, cTCP, cMem,
  1473. }, peerManager.Advertise(aID, 100))
  1474. // Asking for 0 addresses should return, well, 0.
  1475. require.Empty(t, peerManager.Advertise(aID, 0))
  1476. // Asking for 2 addresses should get the highest-rated ones, i.e. a.
  1477. require.ElementsMatch(t, []p2p.NodeAddress{
  1478. aTCP, aMem,
  1479. }, peerManager.Advertise(dID, 2))
  1480. }
  1481. func TestPeerManager_SetHeight_GetHeight(t *testing.T) {
  1482. a := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("a", 40))}
  1483. b := p2p.NodeAddress{Protocol: "memory", NodeID: types.NodeID(strings.Repeat("b", 40))}
  1484. db := dbm.NewMemDB()
  1485. peerManager, err := p2p.NewPeerManager(selfID, db, p2p.PeerManagerOptions{})
  1486. require.NoError(t, err)
  1487. // Getting a height should default to 0, for unknown peers and
  1488. // for known peers without height.
  1489. added, err := peerManager.Add(a)
  1490. require.NoError(t, err)
  1491. require.True(t, added)
  1492. require.EqualValues(t, 0, peerManager.GetHeight(a.NodeID))
  1493. require.EqualValues(t, 0, peerManager.GetHeight(b.NodeID))
  1494. // Setting a height should work for a known node.
  1495. require.NoError(t, peerManager.SetHeight(a.NodeID, 3))
  1496. require.EqualValues(t, 3, peerManager.GetHeight(a.NodeID))
  1497. // Setting a height should add an unknown node.
  1498. require.Equal(t, []types.NodeID{a.NodeID}, peerManager.Peers())
  1499. require.NoError(t, peerManager.SetHeight(b.NodeID, 7))
  1500. require.EqualValues(t, 7, peerManager.GetHeight(b.NodeID))
  1501. require.ElementsMatch(t, []types.NodeID{a.NodeID, b.NodeID}, peerManager.Peers())
  1502. // The heights should not be persisted.
  1503. peerManager.Close()
  1504. peerManager, err = p2p.NewPeerManager(selfID, db, p2p.PeerManagerOptions{})
  1505. require.NoError(t, err)
  1506. require.ElementsMatch(t, []types.NodeID{a.NodeID, b.NodeID}, peerManager.Peers())
  1507. require.Zero(t, peerManager.GetHeight(a.NodeID))
  1508. require.Zero(t, peerManager.GetHeight(b.NodeID))
  1509. }