@@ -68,7 +68,7 @@ use witnet_data_structures::{
6868} ;
6969
7070use witnet_rad:: types:: RadonTypes ;
71- use witnet_util:: timestamp:: seconds_to_human_string;
71+ use witnet_util:: timestamp:: { duration_between_timestamps , seconds_to_human_string} ;
7272use witnet_validations:: validations:: {
7373 compare_block_candidates, validate_block, validate_block_transactions,
7474 validate_new_transaction, validate_rad_request, verify_signatures, VrfSlots ,
@@ -515,7 +515,7 @@ impl ChainManager {
515515 }
516516
517517 #[ allow( clippy:: map_entry) ]
518- fn process_candidate ( & mut self , block : Block ) {
518+ fn process_candidate ( & mut self , ctx : & mut Context < Self > , block : Block , ts : ( i64 , u32 ) ) {
519519 if let ( Some ( current_epoch) , Some ( chain_info) , Some ( rep_engine) , Some ( vrf_ctx) ) = (
520520 self . current_epoch ,
521521 self . chain_state . chain_info . as_ref ( ) ,
@@ -582,7 +582,16 @@ impl ChainManager {
582582 // In order to do not block possible validate candidates in AlmostSynced
583583 // state, we would broadcast the errors too
584584 if self . sm_state == StateMachine :: AlmostSynced {
585- self . broadcast_item ( InventoryItem :: Block ( block) ) ;
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| {
593+ act. broadcast_item ( InventoryItem :: Block ( block) )
594+ } ) ;
586595 }
587596
588597 return ;
@@ -646,7 +655,16 @@ impl ChainManager {
646655 vrf_proof,
647656 } ) ;
648657
649- self . broadcast_item ( InventoryItem :: Block ( block) ) ;
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| {
666+ act. broadcast_item ( InventoryItem :: Block ( block) )
667+ } ) ;
650668 }
651669 Err ( e) => {
652670 log:: warn!(
@@ -658,7 +676,16 @@ impl ChainManager {
658676 // In order to do not block possible validate candidates in AlmostSynced
659677 // state, we would broadcast the errors too
660678 if self . sm_state == StateMachine :: AlmostSynced {
661- self . broadcast_item ( InventoryItem :: Block ( block) ) ;
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| {
687+ act. broadcast_item ( InventoryItem :: Block ( block) )
688+ } ) ;
662689 }
663690 }
664691 }
@@ -2207,6 +2234,30 @@ impl ChainManager {
22072234 }
22082235}
22092236
2237+ // Calculate delay between mining block timestamp and another timestamp
2238+ fn calculate_delay_from_mining_timestamp (
2239+ checkpoint_zero_timestamp : i64 ,
2240+ checkpoints_period : u16 ,
2241+ current_epoch : Epoch ,
2242+ ts : ( i64 , u32 ) ,
2243+ ) -> Duration {
2244+ let epoch_constants = EpochConstants {
2245+ checkpoint_zero_timestamp,
2246+ checkpoints_period,
2247+ } ;
2248+ let timestamp_mining = epoch_constants
2249+ . block_mining_timestamp ( current_epoch)
2250+ . unwrap ( ) ;
2251+
2252+ duration_between_timestamps ( ( timestamp_mining, 0 ) , ts) . unwrap_or_else ( || Duration :: from_secs ( 0 ) )
2253+ }
2254+
2255+ fn delay_function ( initial_delay : Duration ) -> Duration {
2256+ // TODO: Apply a right delay function
2257+ // Direct delay
2258+ initial_delay
2259+ }
2260+
22102261/// Helper struct used to persist an old copy of the `ChainState` to the storage
22112262#[ derive( Debug , Default ) ]
22122263struct ChainStateSnapshot {
@@ -3528,19 +3579,19 @@ mod tests {
35283579 assert_ne ! ( block_1, block_mal_1) ;
35293580
35303581 // Process the modified candidate first
3531- chain_manager. process_candidate ( block_mal_1) ;
3582+ chain_manager. process_candidate ( & mut Context :: new ( ) , block_mal_1, ( 0 , 0 ) ) ;
35323583 // The best candidate should be None because this block is invalid
35333584 let best_cand = chain_manager. best_candidate . as_ref ( ) . map ( |bc| & bc. block ) ;
35343585 assert_eq ! ( best_cand, None ) ;
35353586
35363587 // Process candidate with the same hash, but this one is valid
3537- chain_manager. process_candidate ( block_1. clone ( ) ) ;
3588+ chain_manager. process_candidate ( & mut Context :: new ( ) , block_1. clone ( ) , ( 0 , 0 ) ) ;
35383589 // The best candidate should be block_1
35393590 let best_cand = chain_manager. best_candidate . as_ref ( ) . map ( |bc| & bc. block ) ;
35403591 assert_eq ! ( best_cand, Some ( & block_1) ) ;
35413592
35423593 // Process another valid candidate, but worse than the other one
3543- chain_manager. process_candidate ( block_2) ;
3594+ chain_manager. process_candidate ( & mut Context :: new ( ) , block_2, ( 0 , 0 ) ) ;
35443595 // The best candidate should still be block_1
35453596 let best_cand = chain_manager. best_candidate . as_ref ( ) . map ( |bc| & bc. block ) ;
35463597 assert_eq ! ( best_cand, Some ( & block_1) ) ;
0 commit comments