Skip to content

Commit 19e3cb5

Browse files
committed
chore: override stackerdb smart contract hint-replicas with local hint-replicas if given
1 parent 28134bf commit 19e3cb5

File tree

1 file changed

+99
-82
lines changed

1 file changed

+99
-82
lines changed

stackslib/src/net/stackerdb/config.rs

Lines changed: 99 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,94 @@ impl StackerDBConfig {
285285
Ok(ret)
286286
}
287287

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+
288376
/// Evaluate the contract to get its config
289377
fn eval_config(
290378
chainstate: &mut StacksChainState,
@@ -293,6 +381,7 @@ impl StackerDBConfig {
293381
tip: &StacksBlockId,
294382
signers: Vec<(StacksAddress, u32)>,
295383
local_max_neighbors: u64,
384+
local_hint_replicas: Option<Vec<NeighborAddress>>,
296385
) -> Result<StackerDBConfig, NetError> {
297386
let value =
298387
chainstate.eval_read_only(burn_dbconn, tip, contract_id, "(stackerdb-get-config)")?;
@@ -394,91 +483,17 @@ impl StackerDBConfig {
394483
max_neighbors = u128::from(local_max_neighbors);
395484
}
396485

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'")
409492
.clone()
410493
.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)?;
421494

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+
};
482497

483498
Ok(StackerDBConfig {
484499
chunk_size: chunk_size as u64,
@@ -497,6 +512,7 @@ impl StackerDBConfig {
497512
sortition_db: &SortitionDB,
498513
contract_id: &QualifiedContractIdentifier,
499514
max_neighbors: u64,
515+
local_hint_replicas: Option<Vec<NeighborAddress>>,
500516
) -> Result<StackerDBConfig, NetError> {
501517
let chain_tip =
502518
NakamotoChainState::get_canonical_block_header(chainstate.db(), sortition_db)?
@@ -578,6 +594,7 @@ impl StackerDBConfig {
578594
&chain_tip_hash,
579595
signers,
580596
max_neighbors,
597+
local_hint_replicas,
581598
)?;
582599
Ok(config)
583600
}

0 commit comments

Comments
 (0)