@@ -152,38 +152,31 @@ impl RecordStore for MemoryStore {
152
152
}
153
153
. or_insert_with ( Default :: default) ;
154
154
155
- if let Some ( i) = providers. iter ( ) . position ( |p| p. provider == record. provider ) {
156
- // In-place update of an existing provider record.
157
- providers. as_mut ( ) [ i] = record;
158
- } else {
159
- // It is a new provider record for that key.
160
- let local_key = self . local_key ;
161
- let key = kbucket:: Key :: new ( record. key . clone ( ) ) ;
162
- let provider = kbucket:: Key :: from ( record. provider ) ;
163
- if let Some ( i) = providers. iter ( ) . position ( |p| {
164
- let pk = kbucket:: Key :: from ( p. provider ) ;
165
- provider. distance ( & key) < pk. distance ( & key)
166
- } ) {
167
- // Insert the new provider.
168
- if local_key. preimage ( ) == & record. provider {
155
+ for p in providers. iter_mut ( ) {
156
+ if p. provider == record. provider {
157
+ // In-place update of an existing provider record.
158
+ if self . local_key . preimage ( ) == & record. provider {
159
+ self . provided . remove ( p) ;
169
160
self . provided . insert ( record. clone ( ) ) ;
170
161
}
171
- providers. insert ( i, record) ;
172
- // Remove the excess provider, if any.
173
- if providers. len ( ) > self . config . max_providers_per_key {
174
- if let Some ( p) = providers. pop ( ) {
175
- self . provided . remove ( & p) ;
176
- }
177
- }
178
- } else if providers. len ( ) < self . config . max_providers_per_key {
179
- // The distance of the new provider to the key is larger than
180
- // the distance of any existing provider, but there is still room.
181
- if local_key. preimage ( ) == & record. provider {
182
- self . provided . insert ( record. clone ( ) ) ;
183
- }
184
- providers. push ( record) ;
162
+ * p = record;
163
+ return Ok ( ( ) ) ;
185
164
}
186
165
}
166
+
167
+ // If the providers list is full, we ignore the new provider.
168
+ // This strategy can mitigate Sybil attacks, in which an attacker
169
+ // floods the network with fake provider records.
170
+ if providers. len ( ) == self . config . max_providers_per_key {
171
+ return Ok ( ( ) ) ;
172
+ }
173
+
174
+ // Otherwise, insert the new provider record.
175
+ if self . local_key . preimage ( ) == & record. provider {
176
+ self . provided . insert ( record. clone ( ) ) ;
177
+ }
178
+ providers. push ( record) ;
179
+
187
180
Ok ( ( ) )
188
181
}
189
182
@@ -202,7 +195,9 @@ impl RecordStore for MemoryStore {
202
195
let providers = e. get_mut ( ) ;
203
196
if let Some ( i) = providers. iter ( ) . position ( |p| & p. provider == provider) {
204
197
let p = providers. remove ( i) ;
205
- self . provided . remove ( & p) ;
198
+ if & p. provider == self . local_key . preimage ( ) {
199
+ self . provided . remove ( & p) ;
200
+ }
206
201
}
207
202
if providers. is_empty ( ) {
208
203
e. remove ( ) ;
@@ -221,11 +216,6 @@ mod tests {
221
216
fn random_multihash ( ) -> Multihash < 64 > {
222
217
Multihash :: wrap ( SHA_256_MH , & rand:: thread_rng ( ) . gen :: < [ u8 ; 32 ] > ( ) ) . unwrap ( )
223
218
}
224
-
225
- fn distance ( r : & ProviderRecord ) -> kbucket:: Distance {
226
- kbucket:: Key :: new ( r. key . clone ( ) ) . distance ( & kbucket:: Key :: from ( r. provider ) )
227
- }
228
-
229
219
#[ test]
230
220
fn put_get_remove_record ( ) {
231
221
fn prop ( r : Record ) {
@@ -250,30 +240,6 @@ mod tests {
250
240
quickcheck ( prop as fn ( _) )
251
241
}
252
242
253
- #[ test]
254
- fn providers_ordered_by_distance_to_key ( ) {
255
- fn prop ( providers : Vec < kbucket:: Key < PeerId > > ) -> bool {
256
- let mut store = MemoryStore :: new ( PeerId :: random ( ) ) ;
257
- let key = Key :: from ( random_multihash ( ) ) ;
258
-
259
- let mut records = providers
260
- . into_iter ( )
261
- . map ( |p| ProviderRecord :: new ( key. clone ( ) , p. into_preimage ( ) , Vec :: new ( ) ) )
262
- . collect :: < Vec < _ > > ( ) ;
263
-
264
- for r in & records {
265
- assert ! ( store. add_provider( r. clone( ) ) . is_ok( ) ) ;
266
- }
267
-
268
- records. sort_by_key ( distance) ;
269
- records. truncate ( store. config . max_providers_per_key ) ;
270
-
271
- records == store. providers ( & key) . to_vec ( )
272
- }
273
-
274
- quickcheck ( prop as fn ( _) -> _ )
275
- }
276
-
277
243
#[ test]
278
244
fn provided ( ) {
279
245
let id = PeerId :: random ( ) ;
@@ -302,6 +268,46 @@ mod tests {
302
268
assert_eq ! ( vec![ rec. clone( ) ] , store. providers( & rec. key) . to_vec( ) ) ;
303
269
}
304
270
271
+ #[ test]
272
+ fn update_provided ( ) {
273
+ let prv = PeerId :: random ( ) ;
274
+ let mut store = MemoryStore :: new ( prv) ;
275
+ let key = random_multihash ( ) ;
276
+ let mut rec = ProviderRecord :: new ( key, prv, Vec :: new ( ) ) ;
277
+ assert ! ( store. add_provider( rec. clone( ) ) . is_ok( ) ) ;
278
+ assert_eq ! (
279
+ vec![ Cow :: Borrowed ( & rec) ] ,
280
+ store. provided( ) . collect:: <Vec <_>>( )
281
+ ) ;
282
+ rec. expires = Some ( Instant :: now ( ) ) ;
283
+ assert ! ( store. add_provider( rec. clone( ) ) . is_ok( ) ) ;
284
+ assert_eq ! (
285
+ vec![ Cow :: Borrowed ( & rec) ] ,
286
+ store. provided( ) . collect:: <Vec <_>>( )
287
+ ) ;
288
+ }
289
+
290
+ #[ test]
291
+ fn max_providers_per_key ( ) {
292
+ let config = MemoryStoreConfig :: default ( ) ;
293
+ let key = kbucket:: Key :: new ( Key :: from ( random_multihash ( ) ) ) ;
294
+
295
+ let mut store = MemoryStore :: with_config ( PeerId :: random ( ) , config. clone ( ) ) ;
296
+ let peers = ( 0 ..config. max_providers_per_key )
297
+ . map ( |_| PeerId :: random ( ) )
298
+ . collect :: < Vec < _ > > ( ) ;
299
+ for peer in peers {
300
+ let rec = ProviderRecord :: new ( key. preimage ( ) . clone ( ) , peer, Vec :: new ( ) ) ;
301
+ assert ! ( store. add_provider( rec) . is_ok( ) ) ;
302
+ }
303
+
304
+ // The new provider cannot be added because the key is already saturated.
305
+ let peer = PeerId :: random ( ) ;
306
+ let rec = ProviderRecord :: new ( key. preimage ( ) . clone ( ) , peer, Vec :: new ( ) ) ;
307
+ assert ! ( store. add_provider( rec. clone( ) ) . is_ok( ) ) ;
308
+ assert ! ( !store. providers( & rec. key) . contains( & rec) ) ;
309
+ }
310
+
305
311
#[ test]
306
312
fn max_provided_keys ( ) {
307
313
let mut store = MemoryStore :: new ( PeerId :: random ( ) ) ;
0 commit comments