@@ -68,7 +68,7 @@ use witnet_data_structures::{
68
68
} ;
69
69
70
70
use 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} ;
72
72
use witnet_validations:: validations:: {
73
73
compare_block_candidates, validate_block, validate_block_transactions,
74
74
validate_new_transaction, validate_rad_request, verify_signatures, VrfSlots ,
@@ -515,7 +515,7 @@ impl ChainManager {
515
515
}
516
516
517
517
#[ 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 ) ) {
519
519
if let ( Some ( current_epoch) , Some ( chain_info) , Some ( rep_engine) , Some ( vrf_ctx) ) = (
520
520
self . current_epoch ,
521
521
self . chain_state . chain_info . as_ref ( ) ,
@@ -582,7 +582,16 @@ impl ChainManager {
582
582
// In order to do not block possible validate candidates in AlmostSynced
583
583
// state, we would broadcast the errors too
584
584
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
+ } ) ;
586
595
}
587
596
588
597
return ;
@@ -646,7 +655,16 @@ impl ChainManager {
646
655
vrf_proof,
647
656
} ) ;
648
657
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
+ } ) ;
650
668
}
651
669
Err ( e) => {
652
670
log:: warn!(
@@ -658,7 +676,16 @@ impl ChainManager {
658
676
// In order to do not block possible validate candidates in AlmostSynced
659
677
// state, we would broadcast the errors too
660
678
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
+ } ) ;
662
689
}
663
690
}
664
691
}
@@ -2207,6 +2234,30 @@ impl ChainManager {
2207
2234
}
2208
2235
}
2209
2236
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
+
2210
2261
/// Helper struct used to persist an old copy of the `ChainState` to the storage
2211
2262
#[ derive( Debug , Default ) ]
2212
2263
struct ChainStateSnapshot {
@@ -3528,19 +3579,19 @@ mod tests {
3528
3579
assert_ne ! ( block_1, block_mal_1) ;
3529
3580
3530
3581
// 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 ) ) ;
3532
3583
// The best candidate should be None because this block is invalid
3533
3584
let best_cand = chain_manager. best_candidate . as_ref ( ) . map ( |bc| & bc. block ) ;
3534
3585
assert_eq ! ( best_cand, None ) ;
3535
3586
3536
3587
// 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 ) ) ;
3538
3589
// The best candidate should be block_1
3539
3590
let best_cand = chain_manager. best_candidate . as_ref ( ) . map ( |bc| & bc. block ) ;
3540
3591
assert_eq ! ( best_cand, Some ( & block_1) ) ;
3541
3592
3542
3593
// 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 ) ) ;
3544
3595
// The best candidate should still be block_1
3545
3596
let best_cand = chain_manager. best_candidate . as_ref ( ) . map ( |bc| & bc. block ) ;
3546
3597
assert_eq ! ( best_cand, Some ( & block_1) ) ;
0 commit comments