diff --git a/substrate/client/basic-authorship/src/basic_authorship.rs b/substrate/client/basic-authorship/src/basic_authorship.rs index a24ba31242..b3bf486aae 100644 --- a/substrate/client/basic-authorship/src/basic_authorship.rs +++ b/substrate/client/basic-authorship/src/basic_authorship.rs @@ -212,7 +212,7 @@ impl ProposerInner let mut unqueue_invalid = Vec::new(); let pending_iterator = match executor::block_on(future::select( self.transaction_pool.ready_at(self.parent_number), - futures_timer::Delay::new((deadline - (self.now)()) / 8), + futures_timer::Delay::new(deadline.saturating_duration_since((self.now)()) / 8), )) { Either::Left((iterator, _)) => iterator, Either::Right(_) => { @@ -393,6 +393,36 @@ mod tests { assert_eq!(txpool.ready().count(), 2); } + #[test] + fn should_not_panic_when_deadline_is_reached() { + let client = Arc::new(substrate_test_runtime_client::new()); + let txpool = Arc::new( + BasicPool::new(Default::default(), Arc::new(FullChainApi::new(client.clone()))).0 + ); + + let mut proposer_factory = ProposerFactory::new(client.clone(), txpool.clone()); + + let cell = Mutex::new((false, time::Instant::now())); + let mut proposer = proposer_factory.init_with_now( + &client.header(&BlockId::number(0)).unwrap().unwrap(), + Box::new(move || { + let mut value = cell.lock(); + if !value.0 { + value.0 = true; + return value.1; + } + let new = value.1 + time::Duration::from_secs(160); + *value = (true, new); + new + }) + ); + + let deadline = time::Duration::from_secs(1); + futures::executor::block_on( + proposer.propose(Default::default(), Default::default(), deadline, RecordProof::No) + ).map(|r| r.block).unwrap(); + } + #[test] fn proposed_storage_changes_should_match_execute_block_storage_changes() { let (client, backend) = substrate_test_runtime_client::TestClientBuilder::new()