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.

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