From f862f1abbe6d9bc359ad795b7f918aa287855e86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 24 Aug 2021 10:45:38 +0200 Subject: [PATCH 1/5] Soft limit. --- .../basic-authorship/src/basic_authorship.rs | 96 ++++++++++++++++++- 1 file changed, 91 insertions(+), 5 deletions(-) diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index 144a3ab6850ff..37c31b1b7b84e 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -286,6 +286,11 @@ where } } +/// If the block is full we will attempt to push at most +/// this number of transactions before quitting for real. +/// It allows us to increase block utilization. +const MAX_SKIPPED_TRANSACTIONS: usize = 8; + impl Proposer where A: TransactionPool, @@ -309,11 +314,6 @@ where block_size_limit: Option, ) -> Result, PR::Proof>, sp_blockchain::Error> { - /// If the block is full we will attempt to push at most - /// this number of transactions before quitting for real. - /// It allows us to increase block utilization. - const MAX_SKIPPED_TRANSACTIONS: usize = 8; - let mut block_builder = self.client.new_block_at(&self.parent_id, inherent_digests, PR::ENABLED)?; @@ -336,6 +336,9 @@ where } // proceed with transactions + // We calculate soft deadline used only in case we start skipping transactions. + let now = (self.now)(); + let soft_deadline = now + deadline.saturating_duration_since(now) / 2; let block_timer = time::Instant::now(); let mut skipped = 0; let mut unqueue_invalid = Vec::new(); @@ -386,6 +389,13 @@ where MAX_SKIPPED_TRANSACTIONS - skipped, ); continue + } else if (self.now)() < soft_deadline { + debug!( + "Transaction would overflow the block size limit, \ + but we still have time before the soft deadline, so \ + we will try a bit more." + ); + continue } else { debug!("Reached block size limit, proceeding with proposing."); hit_block_size_limit = true; @@ -406,6 +416,11 @@ where "Block seems full, but will try {} more transactions before quitting.", MAX_SKIPPED_TRANSACTIONS - skipped, ); + } else if (self.now)() < soft_deadline { + debug!( + "Block seems full, but we still have time before the soft deadline, \ + so we will try a bit more before quitting." + ); } else { debug!("Block is full, proceed with proposing."); break @@ -845,4 +860,75 @@ mod tests { // block size and thus, one less transaction should fit into the limit. assert_eq!(block.extrinsics().len(), extrinsics_num - 2); } + + #[test] + fn should_continue_skipping_transactions_up_until_soft_deadline_is_reached() { + // given + let client = Arc::new(substrate_test_runtime_client::new()); + let spawner = sp_core::testing::TaskExecutor::new(); + let txpool = BasicPool::new_full( + Default::default(), + true.into(), + None, + spawner.clone(), + client.clone(), + ); + + block_on(txpool.submit_at(&BlockId::number(0), SOURCE, + (0..MAX_SKIPPED_TRANSACTIONS * 2) + .into_iter() + .map(|i| extrinsic(i as _)) + .collect() + )).unwrap(); + + block_on( + txpool.maintain(chain_event( + client + .header(&BlockId::Number(0u64)) + .expect("header get error") + .expect("there should be header"), + )), + ); + assert_eq!(txpool.ready().count(), MAX_SKIPPED_TRANSACTIONS * 2); + + let mut proposer_factory = + ProposerFactory::new(spawner.clone(), client.clone(), txpool.clone(), None, None); + + let cell = Mutex::new((false, time::Instant::now())); + let 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 old = value.1; + let new = old + time::Duration::from_secs(2); + *value = (true, new); + old + }), + ); + + // when + let deadline = time::Duration::from_secs((MAX_SKIPPED_TRANSACTIONS * 4) as u64); + let block = + block_on(proposer.propose(Default::default(), Default::default(), deadline, None)) + .map(|r| r.block) + .unwrap(); + + // then + // block should have some extrinsics although we have some more in the pool. + assert!( + block.extrinsics().len() > MAX_SKIPPED_TRANSACTIONS, + "Got {}, expected more than {}", + block.extrinsics().len(), + MAX_SKIPPED_TRANSACTIONS + ); + } + + #[test] + fn should_add_more_transactions_when_soft_deadline_is_not_reached() { + assert_eq!(true, false); + } } From d4f8473eae5bac5d2d73dbc46f97b89f2e8cc547 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 31 Aug 2021 16:29:52 +0200 Subject: [PATCH 2/5] Add soft deadline tests. --- .../basic-authorship/src/basic_authorship.rs | 130 ++++++++++++++---- primitives/keyring/src/sr25519.rs | 12 ++ test-utils/runtime/client/src/lib.rs | 16 ++- 3 files changed, 128 insertions(+), 30 deletions(-) diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index 37c31b1b7b84e..aefb4125f4cac 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -367,7 +367,8 @@ where let mut hit_block_size_limit = false; for pending_tx in pending_iterator { - if (self.now)() > deadline { + let now = (self.now)(); + if now > deadline { debug!( "Consensus deadline reached when pushing block transactions, \ proceeding with proposing." @@ -504,6 +505,7 @@ mod tests { use sp_api::Core; use sp_blockchain::HeaderBackend; use sp_consensus::{BlockOrigin, Environment, Proposer}; + use sp_core::Pair; use sp_runtime::traits::NumberFor; use substrate_test_runtime_client::{ prelude::*, @@ -523,6 +525,22 @@ mod tests { .into_signed_tx() } + fn exhausts_resources_extrinsic_from(who: usize) -> Extrinsic { + let pair = AccountKeyring::numeric(who); + let transfer = Transfer { + // increase the amount to bump priority + amount: 1, + nonce: 0, + from: pair.public(), + to: Default::default(), + }; + let signature = pair + .sign(&transfer.encode()) + .into(); + Extrinsic::Transfer { transfer, signature, exhaust_resources_when_not_first: true } + } + + fn chain_event(header: B::Header) -> ChainEvent where NumberFor: From, @@ -568,7 +586,7 @@ mod tests { return value.1 } let old = value.1; - let new = old + time::Duration::from_secs(2); + let new = old + time::Duration::from_secs(1); *value = (true, new); old }), @@ -862,7 +880,7 @@ mod tests { } #[test] - fn should_continue_skipping_transactions_up_until_soft_deadline_is_reached() { + fn should_keep_adding_transactions_after_exhausts_resources_before_soft_deadline() { // given let client = Arc::new(substrate_test_runtime_client::new()); let spawner = sp_core::testing::TaskExecutor::new(); @@ -875,9 +893,16 @@ mod tests { ); block_on(txpool.submit_at(&BlockId::number(0), SOURCE, + // add 2 * MAX_SKIPPED_TRANSACTIONS that exhaust resources (0..MAX_SKIPPED_TRANSACTIONS * 2) .into_iter() - .map(|i| extrinsic(i as _)) + .map(|i| exhausts_resources_extrinsic_from(i)) + // and some transactions that are okay. + .chain( + (0..MAX_SKIPPED_TRANSACTIONS) + .into_iter() + .map(|i| extrinsic(i as _)) + ) .collect() )).unwrap(); @@ -889,46 +914,103 @@ mod tests { .expect("there should be header"), )), ); - assert_eq!(txpool.ready().count(), MAX_SKIPPED_TRANSACTIONS * 2); + assert_eq!(txpool.ready().count(), MAX_SKIPPED_TRANSACTIONS * 3); let mut proposer_factory = ProposerFactory::new(spawner.clone(), client.clone(), txpool.clone(), None, None); - let cell = Mutex::new((false, time::Instant::now())); + let cell = Mutex::new(time::Instant::now()); let 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 old = value.1; - let new = old + time::Duration::from_secs(2); - *value = (true, new); + let old = *value; + *value = old + time::Duration::from_secs(1); old }), ); // when - let deadline = time::Duration::from_secs((MAX_SKIPPED_TRANSACTIONS * 4) as u64); + let deadline = time::Duration::from_secs(300); let block = block_on(proposer.propose(Default::default(), Default::default(), deadline, None)) .map(|r| r.block) .unwrap(); - // then - // block should have some extrinsics although we have some more in the pool. - assert!( - block.extrinsics().len() > MAX_SKIPPED_TRANSACTIONS, - "Got {}, expected more than {}", - block.extrinsics().len(), - MAX_SKIPPED_TRANSACTIONS - ); + // then block should have all non-exhaust resources extrinsics (+ the first one). + assert_eq!(block.extrinsics().len(), MAX_SKIPPED_TRANSACTIONS + 1); } #[test] - fn should_add_more_transactions_when_soft_deadline_is_not_reached() { - assert_eq!(true, false); + fn should_only_skip_up_to_some_limit_after_soft_deadline() { + // given + let client = Arc::new(substrate_test_runtime_client::new()); + let spawner = sp_core::testing::TaskExecutor::new(); + let txpool = BasicPool::new_full( + Default::default(), + true.into(), + None, + spawner.clone(), + client.clone(), + ); + + block_on(txpool.submit_at(&BlockId::number(0), SOURCE, + (0..MAX_SKIPPED_TRANSACTIONS + 2) + .into_iter() + .map(|i| exhausts_resources_extrinsic_from(i)) + // and some transactions that are okay. + .chain( + (0..MAX_SKIPPED_TRANSACTIONS) + .into_iter() + .map(|i| extrinsic(i as _)) + ) + .collect() + )).unwrap(); + + block_on( + txpool.maintain(chain_event( + client + .header(&BlockId::Number(0u64)) + .expect("header get error") + .expect("there should be header"), + )), + ); + assert_eq!(txpool.ready().count(), MAX_SKIPPED_TRANSACTIONS * 2 + 2); + + let mut proposer_factory = + ProposerFactory::new(spawner.clone(), client.clone(), txpool.clone(), None, None); + + let deadline = time::Duration::from_secs(600); + let cell = Arc::new(Mutex::new((0, time::Instant::now()))); + let cell2 = cell.clone(); + let proposer = proposer_factory.init_with_now( + &client.header(&BlockId::number(0)).unwrap().unwrap(), + Box::new(move || { + let mut value = cell.lock(); + let (called, old) = *value; + // add time after deadline is calculated internally (hence 1) + let increase = if called == 1 { + // we start after the soft_deadline should have already been reached. + deadline / 2 + } else { + // but we make sure to never reach the actual deadline + time::Duration::from_millis(0) + }; + *value = (called + 1, old + increase); + old + }), + ); + + let block = + block_on(proposer.propose(Default::default(), Default::default(), deadline, None)) + .map(|r| r.block) + .unwrap(); + + // then the block should have no transactions despite some in the pool + assert_eq!(block.extrinsics().len(), 1); + assert!( + cell2.lock().0 > MAX_SKIPPED_TRANSACTIONS, + "Not enough calls to current time, which indicates the test might have ended because of deadline, not soft deadline" + ); } } diff --git a/primitives/keyring/src/sr25519.rs b/primitives/keyring/src/sr25519.rs index 6a7aa3635a43a..163b20ab3bf5d 100644 --- a/primitives/keyring/src/sr25519.rs +++ b/primitives/keyring/src/sr25519.rs @@ -89,9 +89,21 @@ impl Keyring { pub fn public(self) -> Public { self.pair().public() } + pub fn to_seed(self) -> String { format!("//{}", self) } + + /// Create a crypto `Pair` from a numeric value. + pub fn numeric(idx: usize) -> Pair { + Pair::from_string(&format!("//{}", idx), None) + .expect("numeric values are known good; qed") + } + + /// Get account id of a `numeric` account. + pub fn numeric_id(idx: usize) -> AccountId32 { + (*Self::numeric(idx).public().as_array_ref()).into() + } } impl From for &'static str { diff --git a/test-utils/runtime/client/src/lib.rs b/test-utils/runtime/client/src/lib.rs index dc5ccadc4574f..bcfe93b6f7975 100644 --- a/test-utils/runtime/client/src/lib.rs +++ b/test-utils/runtime/client/src/lib.rs @@ -37,7 +37,7 @@ use sc_client_api::light::{ use sp_core::{ sr25519, storage::{ChildInfo, Storage, StorageChild}, - ChangesTrieConfiguration, + ChangesTrieConfiguration, Pair, }; use sp_runtime::traits::{Block as BlockT, Hash as HashT, HashFor, Header as HeaderT, NumberFor}; use substrate_test_runtime::genesismap::{additional_storage_with_genesis, GenesisConfig}; @@ -118,11 +118,15 @@ impl GenesisParameters { sr25519::Public::from(Sr25519Keyring::Bob).into(), sr25519::Public::from(Sr25519Keyring::Charlie).into(), ], - vec![ - AccountKeyring::Alice.into(), - AccountKeyring::Bob.into(), - AccountKeyring::Charlie.into(), - ], + (0..16_usize) + .into_iter() + .map(|i| AccountKeyring::numeric(i).public()) + .chain(vec![ + AccountKeyring::Alice.into(), + AccountKeyring::Bob.into(), + AccountKeyring::Charlie.into(), + ]) + .collect(), 1000, self.heap_pages_override, self.extra_storage.clone(), From f0dcb32908900aa26314d3c187b93f0b557cc55a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 1 Sep 2021 12:11:31 +0200 Subject: [PATCH 3/5] cargo +nightly fmt --all --- .../basic-authorship/src/basic_authorship.rs | 53 +++++++++---------- primitives/keyring/src/sr25519.rs | 3 +- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index aefb4125f4cac..397bff22ab12e 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -534,13 +534,10 @@ mod tests { from: pair.public(), to: Default::default(), }; - let signature = pair - .sign(&transfer.encode()) - .into(); + let signature = pair.sign(&transfer.encode()).into(); Extrinsic::Transfer { transfer, signature, exhaust_resources_when_not_first: true } } - fn chain_event(header: B::Header) -> ChainEvent where NumberFor: From, @@ -892,19 +889,20 @@ mod tests { client.clone(), ); - block_on(txpool.submit_at(&BlockId::number(0), SOURCE, - // add 2 * MAX_SKIPPED_TRANSACTIONS that exhaust resources - (0..MAX_SKIPPED_TRANSACTIONS * 2) - .into_iter() - .map(|i| exhausts_resources_extrinsic_from(i)) - // and some transactions that are okay. - .chain( - (0..MAX_SKIPPED_TRANSACTIONS) + block_on( + txpool.submit_at( + &BlockId::number(0), + SOURCE, + // add 2 * MAX_SKIPPED_TRANSACTIONS that exhaust resources + (0..MAX_SKIPPED_TRANSACTIONS * 2) .into_iter() - .map(|i| extrinsic(i as _)) - ) - .collect() - )).unwrap(); + .map(|i| exhausts_resources_extrinsic_from(i)) + // and some transactions that are okay. + .chain((0..MAX_SKIPPED_TRANSACTIONS).into_iter().map(|i| extrinsic(i as _))) + .collect(), + ), + ) + .unwrap(); block_on( txpool.maintain(chain_event( @@ -954,18 +952,19 @@ mod tests { client.clone(), ); - block_on(txpool.submit_at(&BlockId::number(0), SOURCE, - (0..MAX_SKIPPED_TRANSACTIONS + 2) - .into_iter() - .map(|i| exhausts_resources_extrinsic_from(i)) - // and some transactions that are okay. - .chain( - (0..MAX_SKIPPED_TRANSACTIONS) + block_on( + txpool.submit_at( + &BlockId::number(0), + SOURCE, + (0..MAX_SKIPPED_TRANSACTIONS + 2) .into_iter() - .map(|i| extrinsic(i as _)) - ) - .collect() - )).unwrap(); + .map(|i| exhausts_resources_extrinsic_from(i)) + // and some transactions that are okay. + .chain((0..MAX_SKIPPED_TRANSACTIONS).into_iter().map(|i| extrinsic(i as _))) + .collect(), + ), + ) + .unwrap(); block_on( txpool.maintain(chain_event( diff --git a/primitives/keyring/src/sr25519.rs b/primitives/keyring/src/sr25519.rs index 163b20ab3bf5d..604c330b1ea1b 100644 --- a/primitives/keyring/src/sr25519.rs +++ b/primitives/keyring/src/sr25519.rs @@ -96,8 +96,7 @@ impl Keyring { /// Create a crypto `Pair` from a numeric value. pub fn numeric(idx: usize) -> Pair { - Pair::from_string(&format!("//{}", idx), None) - .expect("numeric values are known good; qed") + Pair::from_string(&format!("//{}", idx), None).expect("numeric values are known good; qed") } /// Get account id of a `numeric` account. From b62732d2f6384625795ce1a610af2c8f7569e081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 14 Sep 2021 16:47:36 +0200 Subject: [PATCH 4/5] Fix sc-service test. --- Cargo.lock | 1 + client/service/test/Cargo.toml | 1 + client/service/test/src/client/mod.rs | 41 ++++++++++++++++++++------- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1bcdb75229561..0012269ae4053 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8147,6 +8147,7 @@ version = "2.0.0" dependencies = [ "fdlimit", "futures 0.3.16", + "hex", "hex-literal", "log 0.4.14", "parity-scale-codec", diff --git a/client/service/test/Cargo.toml b/client/service/test/Cargo.toml index 85a6dcc9e8b29..9e66e9ca381d3 100644 --- a/client/service/test/Cargo.toml +++ b/client/service/test/Cargo.toml @@ -12,6 +12,7 @@ repository = "https://github.com/paritytech/substrate/" targets = ["x86_64-unknown-linux-gnu"] [dependencies] +hex = "0.4" hex-literal = "0.3.1" tempfile = "3.1.0" tokio = { version = "1.10.0", features = ["time"] } diff --git a/client/service/test/src/client/mod.rs b/client/service/test/src/client/mod.rs index 295e941f7ceb1..0a573a7a931b5 100644 --- a/client/service/test/src/client/mod.rs +++ b/client/service/test/src/client/mod.rs @@ -2033,12 +2033,21 @@ fn storage_keys_iter_works() { let res: Vec<_> = client .storage_keys_iter(&BlockId::Number(0), Some(&prefix), None) .unwrap() - .take(2) - .map(|x| x.0) + .take(8) + .map(|x| hex::encode(&x.0)) .collect(); assert_eq!( res, - [hex!("0befda6e1ca4ef40219d588a727f1271").to_vec(), hex!("3a636f6465").to_vec()] + [ + "00c232cf4e70a5e343317016dc805bf80a6a8cd8ad39958d56f99891b07851e0", + "085b2407916e53a86efeb8b72dbe338c4b341dab135252f96b6ed8022209b6cb", + "0befda6e1ca4ef40219d588a727f1271", + "1a560ecfd2a62c2b8521ef149d0804eb621050e3988ed97dca55f0d7c3e6aa34", + "1d66850d32002979d67dd29dc583af5b2ae2a1f71c1f35ad90fff122be7a3824", + "237498b98d8803334286e9f0483ef513098dd3c1c22ca21c4dc155b4ef6cc204", + "29b9db10ec5bf7907d8f74b5e60aa8140c4fbdd8127a1ee5600cb98e5ec01729", + "3a636f6465", + ] ); let res: Vec<_> = client @@ -2048,15 +2057,19 @@ fn storage_keys_iter_works() { Some(&StorageKey(hex!("3a636f6465").to_vec())), ) .unwrap() - .take(3) - .map(|x| x.0) + .take(7) + .map(|x| hex::encode(&x.0)) .collect(); assert_eq!( res, [ - hex!("3a686561707061676573").to_vec(), - hex!("6644b9b8bc315888ac8e41a7968dc2b4141a5403c58acdf70b7e8f7e07bf5081").to_vec(), - hex!("79c07e2b1d2e2abfd4855b936617eeff5e0621c4869aa60c02be9adcc98a0d1d").to_vec(), + "3a686561707061676573", + "52008686cc27f6e5ed83a216929942f8bcd32a396f09664a5698f81371934b56", + "5348d72ac6cc66e5d8cbecc27b0e0677503b845fe2382d819f83001781788fd5", + "5c2d5fda66373dabf970e4fb13d277ce91c5233473321129d32b5a8085fa8133", + "6644b9b8bc315888ac8e41a7968dc2b4141a5403c58acdf70b7e8f7e07bf5081", + "66484000ed3f75c95fc7b03f39c20ca1e1011e5999278247d3b2f5e3c3273808", + "79c07e2b1d2e2abfd4855b936617eeff5e0621c4869aa60c02be9adcc98a0d1d", ] ); @@ -2069,12 +2082,18 @@ fn storage_keys_iter_works() { )), ) .unwrap() - .take(1) - .map(|x| x.0) + .take(5) + .map(|x| hex::encode(x.0)) .collect(); assert_eq!( res, - [hex!("cf722c0832b5231d35e29f319ff27389f5032bfc7bfc3ba5ed7839f2042fb99f").to_vec()] + [ + "7d5007603a7f5dd729d51d93cf695d6465789443bb967c0d1fe270e388c96eaa", + "811ecfaadcf5f2ee1d67393247e2f71a1662d433e8ce7ff89fb0d4aa9561820b", + "a93d74caa7ec34ea1b04ce1e5c090245f867d333f0f88278a451e45299654dc5", + "a9ee1403384afbfc13f13be91ff70bfac057436212e53b9733914382ac942892", + "cf722c0832b5231d35e29f319ff27389f5032bfc7bfc3ba5ed7839f2042fb99f", + ] ); } From 04903c9bfea8962a6d0a6805e4cb7511ebfc819e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 1 Oct 2021 16:26:18 +0200 Subject: [PATCH 5/5] Improving tests --- client/basic-authorship/src/basic_authorship.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index eb8fff8ed280f..2b8f6af7a6c32 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -390,7 +390,7 @@ where MAX_SKIPPED_TRANSACTIONS - skipped, ); continue - } else if (self.now)() < soft_deadline { + } else if now < soft_deadline { debug!( "Transaction would overflow the block size limit, \ but we still have time before the soft deadline, so \ @@ -756,8 +756,8 @@ mod tests { // then // block should have some extrinsics although we have some more in the pool. - assert_eq!(block.extrinsics().len(), expected_block_extrinsics); assert_eq!(txpool.ready().count(), expected_pool_transactions); + assert_eq!(block.extrinsics().len(), expected_block_extrinsics); block }; @@ -770,6 +770,7 @@ mod tests { .expect("there should be header"), )), ); + assert_eq!(txpool.ready().count(), 7); // let's create one block and import it let block = propose_block(&client, 0, 2, 7); @@ -783,6 +784,7 @@ mod tests { .expect("there should be header"), )), ); + assert_eq!(txpool.ready().count(), 5); // now let's make sure that we can still make some progress let block = propose_block(&client, 1, 2, 5); @@ -929,7 +931,8 @@ mod tests { ); // when - let deadline = time::Duration::from_secs(300); + // give it enough time so that deadline is never triggered. + let deadline = time::Duration::from_secs(900); let block = block_on(proposer.propose(Default::default(), Default::default(), deadline, None)) .map(|r| r.block)