1
1
use cuprate_p2p_core:: client:: { Client , InternalPeerID } ;
2
- use cuprate_p2p_core:: NetworkZone ;
3
- use indexmap:: IndexMap ;
2
+ use cuprate_p2p_core:: { ConnectionDirection , NetworkZone } ;
3
+ use indexmap:: { IndexMap , IndexSet } ;
4
+ use rand:: seq:: index;
5
+ use rand:: thread_rng;
4
6
use std:: future:: { ready, Ready } ;
5
7
use std:: task:: { Context , Poll } ;
6
8
use tokio:: sync:: mpsc;
@@ -15,6 +17,7 @@ use cuprate_helper::cast::u64_to_usize;
15
17
pub enum PeerSetRequest {
16
18
MostPoWSeen ,
17
19
PeersWithMorePoW ( u128 ) ,
20
+ StemPeer ,
18
21
}
19
22
20
23
pub enum PeerSetResponse < N : NetworkZone > {
@@ -24,23 +27,30 @@ pub enum PeerSetResponse<N: NetworkZone> {
24
27
top_hash : [ u8 ; 32 ] ,
25
28
} ,
26
29
PeersWithMorePoW ( Vec < ClientDropGuard < N > > ) ,
30
+ StemPeer ( Option < ClientDropGuard < N > > ) ,
27
31
}
28
32
29
33
pub ( crate ) struct PeerSet < N : NetworkZone > {
30
34
peers : IndexMap < InternalPeerID < N :: Addr > , StoredClient < N > > ,
35
+ outbound_peers : IndexSet < InternalPeerID < N :: Addr > > ,
31
36
new_peers : mpsc:: Receiver < Client < N > > ,
32
37
}
33
38
34
39
impl < N : NetworkZone > PeerSet < N > {
35
40
pub ( crate ) fn new ( new_peers : mpsc:: Receiver < Client < N > > ) -> Self {
36
41
Self {
37
42
peers : IndexMap :: new ( ) ,
43
+ outbound_peers : IndexSet :: new ( ) ,
38
44
new_peers,
39
45
}
40
46
}
41
47
42
48
fn poll_new_peers ( & mut self , cx : & mut Context < ' _ > ) {
43
49
while let Poll :: Ready ( Some ( new_peer) ) = self . new_peers . poll_recv ( cx) {
50
+ if new_peer. info . direction == ConnectionDirection :: Outbound {
51
+ self . outbound_peers . insert ( new_peer. info . id ) ;
52
+ }
53
+
44
54
self . peers
45
55
. insert ( new_peer. info . id , StoredClient :: new ( new_peer) ) ;
46
56
}
@@ -49,9 +59,14 @@ impl<N: NetworkZone> PeerSet<N> {
49
59
fn remove_dead_peers ( & mut self ) {
50
60
let mut i = 0 ;
51
61
while i < self . peers . len ( ) {
52
- if self . peers [ i] . client . alive ( ) {
62
+ let peer = & self . peers [ i] ;
63
+ if peer. client . alive ( ) {
53
64
i += 1 ;
54
65
} else {
66
+ if peer. client . info . direction == ConnectionDirection :: Outbound {
67
+ self . outbound_peers . swap_remove ( & peer. client . info . id ) ;
68
+ }
69
+
55
70
self . peers . swap_remove_index ( i) ;
56
71
}
57
72
}
@@ -83,21 +98,43 @@ impl<N: NetworkZone> PeerSet<N> {
83
98
PeerSetResponse :: PeersWithMorePoW (
84
99
self . peers
85
100
. values ( )
86
- . filter_map ( | client| {
87
- ( !client. is_downloading_blocks ( )
101
+ . filter ( | & client| {
102
+ !client. is_downloading_blocks ( )
88
103
&& client
89
104
. client
90
105
. info
91
106
. core_sync_data
92
107
. lock ( )
93
108
. unwrap ( )
94
109
. cumulative_difficulty ( )
95
- > cumulative_difficulty)
96
- . then ( || client. downloading_blocks_guard ( ) )
110
+ > cumulative_difficulty
97
111
} )
112
+ . map ( StoredClient :: downloading_blocks_guard)
98
113
. collect ( ) ,
99
114
)
100
115
}
116
+
117
+ fn random_peer_for_stem ( & self ) -> PeerSetResponse < N > {
118
+ let outbound_peers = index:: sample (
119
+ & mut thread_rng ( ) ,
120
+ self . outbound_peers . len ( ) ,
121
+ self . outbound_peers . len ( ) ,
122
+ ) ;
123
+
124
+ for peer in outbound_peers
125
+ . into_iter ( )
126
+ . map ( |i| self . outbound_peers . get_index ( i) . unwrap ( ) )
127
+ {
128
+ let client = self . peers . get ( peer) . unwrap ( ) ;
129
+ if client. is_a_stem_peer ( ) {
130
+ continue ;
131
+ }
132
+
133
+ return PeerSetResponse :: StemPeer ( Some ( client. stem_peer_guard ( ) ) ) ;
134
+ }
135
+
136
+ PeerSetResponse :: StemPeer ( None )
137
+ }
101
138
}
102
139
103
140
impl < N : NetworkZone > Service < PeerSetRequest > for PeerSet < N > {
@@ -120,6 +157,7 @@ impl<N: NetworkZone> Service<PeerSetRequest> for PeerSet<N> {
120
157
PeerSetRequest :: PeersWithMorePoW ( cumulative_difficulty) => {
121
158
Ok ( self . peers_with_more_pow ( cumulative_difficulty) )
122
159
}
160
+ PeerSetRequest :: StemPeer => Ok ( self . random_peer_for_stem ( ) ) ,
123
161
} )
124
162
}
125
163
}
0 commit comments