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.

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