Skip to content

Commit f244e58

Browse files
committed
feat(node): avoid broadcasting if delay is too big
1 parent add3d9a commit f244e58

File tree

1 file changed

+47
-33
lines changed
  • node/src/actors/chain_manager

1 file changed

+47
-33
lines changed

node/src/actors/chain_manager/mod.rs

+47-33
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,20 @@ impl ChainManager {
551551
return;
552552
}
553553

554+
// Calculate delay for broadcasting blocks
555+
let delay = if let Some(delay) = calculate_delay_for_broadcasting_block(
556+
chain_info.consensus_constants.checkpoint_zero_timestamp,
557+
chain_info.consensus_constants.checkpoints_period,
558+
current_epoch,
559+
ts,
560+
) {
561+
delay
562+
} else {
563+
log::debug!("Block received too late to broadcasting");
564+
565+
return;
566+
};
567+
554568
let mut vrf_input = chain_info.highest_vrf_output;
555569
vrf_input.checkpoint = current_epoch;
556570
let active_wips = ActiveWips {
@@ -582,14 +596,7 @@ impl ChainManager {
582596
// In order to do not block possible validate candidates in AlmostSynced
583597
// state, we would broadcast the errors too
584598
if self.sm_state == StateMachine::AlmostSynced {
585-
let delay = calculate_delay_from_mining_timestamp(
586-
chain_info.consensus_constants.checkpoint_zero_timestamp,
587-
chain_info.consensus_constants.checkpoints_period,
588-
current_epoch,
589-
ts,
590-
);
591-
592-
ctx.run_later(delay_function(delay), |act, _ctx| {
599+
ctx.run_later(delay, |act, _ctx| {
593600
act.broadcast_item(InventoryItem::Block(block))
594601
});
595602
}
@@ -655,14 +662,7 @@ impl ChainManager {
655662
vrf_proof,
656663
});
657664

658-
let delay = calculate_delay_from_mining_timestamp(
659-
chain_info.consensus_constants.checkpoint_zero_timestamp,
660-
chain_info.consensus_constants.checkpoints_period,
661-
current_epoch,
662-
ts,
663-
);
664-
665-
ctx.run_later(delay_function(delay), |act, _ctx| {
665+
ctx.run_later(delay, |act, _ctx| {
666666
act.broadcast_item(InventoryItem::Block(block))
667667
});
668668
}
@@ -676,14 +676,7 @@ impl ChainManager {
676676
// In order to do not block possible validate candidates in AlmostSynced
677677
// state, we would broadcast the errors too
678678
if self.sm_state == StateMachine::AlmostSynced {
679-
let delay = calculate_delay_from_mining_timestamp(
680-
chain_info.consensus_constants.checkpoint_zero_timestamp,
681-
chain_info.consensus_constants.checkpoints_period,
682-
current_epoch,
683-
ts,
684-
);
685-
686-
ctx.run_later(delay_function(delay), |act, _ctx| {
679+
ctx.run_later(delay, |act, _ctx| {
687680
act.broadcast_item(InventoryItem::Block(block))
688681
});
689682
}
@@ -2234,28 +2227,49 @@ impl ChainManager {
22342227
}
22352228
}
22362229

2237-
// Calculate delay between mining block timestamp and another timestamp
2238-
fn calculate_delay_from_mining_timestamp(
2230+
// Auxiliary function that converts one delay in another
2231+
fn delay_function(initial_delay: Duration) -> Duration {
2232+
// TODO: Apply a right delay function
2233+
// Direct delay
2234+
initial_delay
2235+
}
2236+
2237+
// Calculate the delay to introduce in block broadcasting
2238+
// Returns None in case of overflow the current epoch duration
2239+
#[allow(clippy::cast_sign_loss)]
2240+
fn calculate_delay_for_broadcasting_block(
22392241
checkpoint_zero_timestamp: i64,
22402242
checkpoints_period: u16,
22412243
current_epoch: Epoch,
22422244
ts: (i64, u32),
2243-
) -> Duration {
2245+
) -> Option<Duration> {
22442246
let epoch_constants = EpochConstants {
22452247
checkpoint_zero_timestamp,
22462248
checkpoints_period,
22472249
};
2250+
2251+
// Calculate delay between mining block timestamp and another timestamp
22482252
let timestamp_mining = epoch_constants
22492253
.block_mining_timestamp(current_epoch)
22502254
.unwrap();
2255+
let delay_from_mining_ts = duration_between_timestamps((timestamp_mining, 0), ts)
2256+
.unwrap_or_else(|| Duration::from_secs(0));
22512257

2252-
duration_between_timestamps((timestamp_mining, 0), ts).unwrap_or_else(|| Duration::from_secs(0))
2253-
}
2258+
// Apply magic delay function
2259+
let delay_to_broadcasting = delay_function(delay_from_mining_ts);
22542260

2255-
fn delay_function(initial_delay: Duration) -> Duration {
2256-
// TODO: Apply a right delay function
2257-
// Direct delay
2258-
initial_delay
2261+
// Return delay only if is before the end of the epoch
2262+
let end_epoch_ts = epoch_constants
2263+
.epoch_timestamp(current_epoch + 1)
2264+
.unwrap_or(i64::MAX) as u64;
2265+
let ts_with_delay = Duration::new(ts.0 as u64, ts.1).checked_add(delay_to_broadcasting);
2266+
2267+
match ts_with_delay {
2268+
Some(ts_with_delay) if ts_with_delay.as_secs() < end_epoch_ts => {
2269+
Some(delay_to_broadcasting)
2270+
}
2271+
_ => None,
2272+
}
22592273
}
22602274

22612275
/// Helper struct used to persist an old copy of the `ChainState` to the storage

0 commit comments

Comments
 (0)