@@ -285,6 +285,94 @@ impl StackerDBConfig {
285
285
Ok ( ret)
286
286
}
287
287
288
+ /// Evaluate contract-given hint-replicas
289
+ fn eval_hint_replicas (
290
+ contract_id : & QualifiedContractIdentifier ,
291
+ hint_replicas_list : Vec < ClarityValue > ,
292
+ ) -> Result < Vec < NeighborAddress > , NetError > {
293
+ let mut hint_replicas = vec ! [ ] ;
294
+ for hint_replica_value in hint_replicas_list. into_iter ( ) {
295
+ let hint_replica_data = hint_replica_value. expect_tuple ( ) ?;
296
+
297
+ let addr_byte_list = hint_replica_data
298
+ . get ( "addr" )
299
+ . expect ( "FATAL: missing 'addr'" )
300
+ . clone ( )
301
+ . expect_list ( ) ?;
302
+ let port = hint_replica_data
303
+ . get ( "port" )
304
+ . expect ( "FATAL: missing 'port'" )
305
+ . clone ( )
306
+ . expect_u128 ( ) ?;
307
+ let pubkey_hash_bytes = hint_replica_data
308
+ . get ( "public-key-hash" )
309
+ . expect ( "FATAL: missing 'public-key-hash" )
310
+ . clone ( )
311
+ . expect_buff_padded ( 20 , 0 ) ?;
312
+
313
+ let mut addr_bytes = vec ! [ ] ;
314
+ for byte_val in addr_byte_list. into_iter ( ) {
315
+ let byte = byte_val. expect_u128 ( ) ?;
316
+ if byte > ( u8:: MAX as u128 ) {
317
+ let reason = format ! (
318
+ "Contract {} stipulates an addr byte above u8::MAX" ,
319
+ contract_id
320
+ ) ;
321
+ warn ! ( "{}" , & reason) ;
322
+ return Err ( NetError :: InvalidStackerDBContract (
323
+ contract_id. clone ( ) ,
324
+ reason,
325
+ ) ) ;
326
+ }
327
+ addr_bytes. push ( byte as u8 ) ;
328
+ }
329
+ if addr_bytes. len ( ) != 16 {
330
+ let reason = format ! (
331
+ "Contract {} did not stipulate a full 16-octet IP address" ,
332
+ contract_id
333
+ ) ;
334
+ warn ! ( "{}" , & reason) ;
335
+ return Err ( NetError :: InvalidStackerDBContract (
336
+ contract_id. clone ( ) ,
337
+ reason,
338
+ ) ) ;
339
+ }
340
+
341
+ if port < 1024 || port > u128:: from ( u16:: MAX - 1 ) {
342
+ let reason = format ! (
343
+ "Contract {} stipulates a port lower than 1024 or above u16::MAX - 1" ,
344
+ contract_id
345
+ ) ;
346
+ warn ! ( "{}" , & reason) ;
347
+ return Err ( NetError :: InvalidStackerDBContract (
348
+ contract_id. clone ( ) ,
349
+ reason,
350
+ ) ) ;
351
+ }
352
+ // NOTE: port is now known to be in range [1024, 65535]
353
+
354
+ let mut pubkey_hash_slice = [ 0u8 ; 20 ] ;
355
+ pubkey_hash_slice. copy_from_slice ( & pubkey_hash_bytes[ 0 ..20 ] ) ;
356
+
357
+ let peer_addr = PeerAddress :: from_slice ( & addr_bytes) . expect ( "FATAL: not 16 bytes" ) ;
358
+ if peer_addr. is_in_private_range ( ) {
359
+ debug ! (
360
+ "Ignoring private IP address '{}' in hint-replicas" ,
361
+ & peer_addr. to_socketaddr( port as u16 )
362
+ ) ;
363
+ continue ;
364
+ }
365
+
366
+ let naddr = NeighborAddress {
367
+ addrbytes : peer_addr,
368
+ port : port as u16 ,
369
+ public_key_hash : Hash160 ( pubkey_hash_slice) ,
370
+ } ;
371
+ hint_replicas. push ( naddr) ;
372
+ }
373
+ Ok ( hint_replicas)
374
+ }
375
+
288
376
/// Evaluate the contract to get its config
289
377
fn eval_config (
290
378
chainstate : & mut StacksChainState ,
@@ -293,6 +381,7 @@ impl StackerDBConfig {
293
381
tip : & StacksBlockId ,
294
382
signers : Vec < ( StacksAddress , u32 ) > ,
295
383
local_max_neighbors : u64 ,
384
+ local_hint_replicas : Option < Vec < NeighborAddress > > ,
296
385
) -> Result < StackerDBConfig , NetError > {
297
386
let value =
298
387
chainstate. eval_read_only ( burn_dbconn, tip, contract_id, "(stackerdb-get-config)" ) ?;
@@ -394,91 +483,17 @@ impl StackerDBConfig {
394
483
max_neighbors = u128:: from ( local_max_neighbors) ;
395
484
}
396
485
397
- let hint_replicas_list = config_tuple
398
- . get ( "hint-replicas" )
399
- . expect ( "FATAL: missing 'hint-replicas'" )
400
- . clone ( )
401
- . expect_list ( ) ?;
402
- let mut hint_replicas = vec ! [ ] ;
403
- for hint_replica_value in hint_replicas_list. into_iter ( ) {
404
- let hint_replica_data = hint_replica_value. expect_tuple ( ) ?;
405
-
406
- let addr_byte_list = hint_replica_data
407
- . get ( "addr" )
408
- . expect ( "FATAL: missing 'addr'" )
486
+ let hint_replicas = if let Some ( replicas) = local_hint_replicas {
487
+ replicas. clone ( )
488
+ } else {
489
+ let hint_replicas_list = config_tuple
490
+ . get ( "hint-replicas" )
491
+ . expect ( "FATAL: missing 'hint-replicas'" )
409
492
. clone ( )
410
493
. expect_list ( ) ?;
411
- let port = hint_replica_data
412
- . get ( "port" )
413
- . expect ( "FATAL: missing 'port'" )
414
- . clone ( )
415
- . expect_u128 ( ) ?;
416
- let pubkey_hash_bytes = hint_replica_data
417
- . get ( "public-key-hash" )
418
- . expect ( "FATAL: missing 'public-key-hash" )
419
- . clone ( )
420
- . expect_buff_padded ( 20 , 0 ) ?;
421
494
422
- let mut addr_bytes = vec ! [ ] ;
423
- for byte_val in addr_byte_list. into_iter ( ) {
424
- let byte = byte_val. expect_u128 ( ) ?;
425
- if byte > ( u8:: MAX as u128 ) {
426
- let reason = format ! (
427
- "Contract {} stipulates an addr byte above u8::MAX" ,
428
- contract_id
429
- ) ;
430
- warn ! ( "{}" , & reason) ;
431
- return Err ( NetError :: InvalidStackerDBContract (
432
- contract_id. clone ( ) ,
433
- reason,
434
- ) ) ;
435
- }
436
- addr_bytes. push ( byte as u8 ) ;
437
- }
438
- if addr_bytes. len ( ) != 16 {
439
- let reason = format ! (
440
- "Contract {} did not stipulate a full 16-octet IP address" ,
441
- contract_id
442
- ) ;
443
- warn ! ( "{}" , & reason) ;
444
- return Err ( NetError :: InvalidStackerDBContract (
445
- contract_id. clone ( ) ,
446
- reason,
447
- ) ) ;
448
- }
449
-
450
- if port < 1024 || port > u128:: from ( u16:: MAX - 1 ) {
451
- let reason = format ! (
452
- "Contract {} stipulates a port lower than 1024 or above u16::MAX - 1" ,
453
- contract_id
454
- ) ;
455
- warn ! ( "{}" , & reason) ;
456
- return Err ( NetError :: InvalidStackerDBContract (
457
- contract_id. clone ( ) ,
458
- reason,
459
- ) ) ;
460
- }
461
- // NOTE: port is now known to be in range [1024, 65535]
462
-
463
- let mut pubkey_hash_slice = [ 0u8 ; 20 ] ;
464
- pubkey_hash_slice. copy_from_slice ( & pubkey_hash_bytes[ 0 ..20 ] ) ;
465
-
466
- let peer_addr = PeerAddress :: from_slice ( & addr_bytes) . expect ( "FATAL: not 16 bytes" ) ;
467
- if peer_addr. is_in_private_range ( ) {
468
- debug ! (
469
- "Ignoring private IP address '{}' in hint-replicas" ,
470
- & peer_addr. to_socketaddr( port as u16 )
471
- ) ;
472
- continue ;
473
- }
474
-
475
- let naddr = NeighborAddress {
476
- addrbytes : peer_addr,
477
- port : port as u16 ,
478
- public_key_hash : Hash160 ( pubkey_hash_slice) ,
479
- } ;
480
- hint_replicas. push ( naddr) ;
481
- }
495
+ Self :: eval_hint_replicas ( contract_id, hint_replicas_list) ?
496
+ } ;
482
497
483
498
Ok ( StackerDBConfig {
484
499
chunk_size : chunk_size as u64 ,
@@ -497,6 +512,7 @@ impl StackerDBConfig {
497
512
sortition_db : & SortitionDB ,
498
513
contract_id : & QualifiedContractIdentifier ,
499
514
max_neighbors : u64 ,
515
+ local_hint_replicas : Option < Vec < NeighborAddress > > ,
500
516
) -> Result < StackerDBConfig , NetError > {
501
517
let chain_tip =
502
518
NakamotoChainState :: get_canonical_block_header ( chainstate. db ( ) , sortition_db) ?
@@ -578,6 +594,7 @@ impl StackerDBConfig {
578
594
& chain_tip_hash,
579
595
signers,
580
596
max_neighbors,
597
+ local_hint_replicas,
581
598
) ?;
582
599
Ok ( config)
583
600
}
0 commit comments