From 83a50952be82965e1b554e854f11668941f5912d Mon Sep 17 00:00:00 2001 From: lemunozm Date: Thu, 26 Oct 2023 19:31:11 +0200 Subject: [PATCH] Support jumping to future blocks --- .../src/generic/cases/example.rs | 17 ++++++- runtime/integration-tests/src/generic/env.rs | 50 +++++++++++++------ .../src/generic/envs/fudge_env.rs | 6 ++- 3 files changed, 57 insertions(+), 16 deletions(-) diff --git a/runtime/integration-tests/src/generic/cases/example.rs b/runtime/integration-tests/src/generic/cases/example.rs index 694e94a25a..6e4bd4310a 100644 --- a/runtime/integration-tests/src/generic/cases/example.rs +++ b/runtime/integration-tests/src/generic/cases/example.rs @@ -1,4 +1,5 @@ -use cfg_primitives::{Balance, CFG}; +use cfg_primitives::{Balance, CFG, SECONDS_PER_YEAR}; +use cfg_traits::IntoSeconds; use frame_support::traits::Get; use sp_api::runtime_decl_for_Core::CoreV4; @@ -156,7 +157,21 @@ fn fudge_call_api() { }) } +fn pass_time_one_block() { + let mut env = RuntimeEnv::::from_storage(Default::default()); + + let before = env.state(|| pallet_timestamp::Pallet::::get()); + + // Not supported in fudge + env.pass(Blocks::JumpBySeconds(SECONDS_PER_YEAR)); + + let after = env.state(|| pallet_timestamp::Pallet::::get()); + + assert_eq!((after - before).into_seconds(), SECONDS_PER_YEAR) +} + crate::test_for_runtimes!([development, altair, centrifuge], transfer_balance); crate::test_for_runtimes!(all, call_api); crate::test_for_runtimes!(all, fudge_transfer_balance); crate::test_for_runtimes!(all, fudge_call_api); +crate::test_for_runtimes!(all, pass_time_one_block); diff --git a/runtime/integration-tests/src/generic/env.rs b/runtime/integration-tests/src/generic/env.rs index d8dd5a48e4..1d37a6b0aa 100644 --- a/runtime/integration-tests/src/generic/env.rs +++ b/runtime/integration-tests/src/generic/env.rs @@ -24,26 +24,37 @@ pub enum Blocks { /// Pass a number of block until find an event or reach the limit UntilEvent { event: Event, limit: BlockNumber }, + + /// Jumps to a block in the future to reach the requested time. + /// Only one real block is created in the process. + /// This can be used to emulate passing time during long periods + /// computationally very fast. + /// (i.e. years) + JumpBySeconds(Seconds), } impl Blocks { fn range_for(&self, current: BlockNumber, slot_duration: Seconds) -> Range { - let blocks = match self { - Blocks::ByNumber(n) => *n, + let next = current + 1; + let (from, to) = match self { + Blocks::ByNumber(n) => (next, next + *n), Blocks::BySeconds(secs) => { - let n = secs / slot_duration; + let mut blocks = (secs / slot_duration) as BlockNumber; if secs % slot_duration != 0 { - n as BlockNumber + 1 - } else { - n as BlockNumber - } + blocks += 1 + }; + (next, next + blocks) + } + Blocks::UntilEvent { limit, .. } => (next, next + *limit), + Blocks::JumpBySeconds(secs) => { + let mut blocks = (secs / slot_duration) as BlockNumber; + if secs % slot_duration != 0 { + blocks += 1 + }; + (next + blocks.saturating_sub(1), next + blocks) } - Blocks::UntilEvent { limit, .. } => *limit, }; - - dbg!(blocks); - - (current + 1)..(current + 1 + blocks) + from..to } } @@ -162,6 +173,7 @@ mod tests { struct MockEnv; const SLOT_DURATION: Seconds = 12; + const EMPTY: [BlockNumber; 0] = []; fn blocks_from(current: BlockNumber, blocks: Blocks<()>) -> Vec { blocks @@ -172,11 +184,21 @@ mod tests { #[test] fn by_seconds() { - assert_eq!(blocks_from(0, Blocks::BySeconds(0)), [] as [BlockNumber; 0]); + assert_eq!(blocks_from(0, Blocks::BySeconds(0)), EMPTY); assert_eq!(blocks_from(0, Blocks::BySeconds(1)), [1]); assert_eq!(blocks_from(0, Blocks::BySeconds(12)), [1]); - assert_eq!(blocks_from(5, Blocks::BySeconds(0)), [] as [BlockNumber; 0]); + assert_eq!(blocks_from(5, Blocks::BySeconds(0)), EMPTY); assert_eq!(blocks_from(5, Blocks::BySeconds(12)), [6]); assert_eq!(blocks_from(5, Blocks::BySeconds(60)), [6, 7, 8, 9, 10]); } + + #[test] + fn by_seconds_fast() { + assert_eq!(blocks_from(0, Blocks::JumpBySeconds(0)), EMPTY); + assert_eq!(blocks_from(0, Blocks::JumpBySeconds(1)), [1]); + assert_eq!(blocks_from(0, Blocks::JumpBySeconds(12)), [1]); + assert_eq!(blocks_from(5, Blocks::JumpBySeconds(0)), EMPTY); + assert_eq!(blocks_from(5, Blocks::JumpBySeconds(12)), [6]); + assert_eq!(blocks_from(5, Blocks::JumpBySeconds(60)), [10]); + } } diff --git a/runtime/integration-tests/src/generic/envs/fudge_env.rs b/runtime/integration-tests/src/generic/envs/fudge_env.rs index e30c1936d6..76db6147c1 100644 --- a/runtime/integration-tests/src/generic/envs/fudge_env.rs +++ b/runtime/integration-tests/src/generic/envs/fudge_env.rs @@ -76,7 +76,11 @@ impl Env for FudgeEnv { self.handle.parachain().with_state(f).unwrap() } - fn __priv_build_block(&mut self, _i: BlockNumber) { + fn __priv_build_block(&mut self, i: BlockNumber) { + let current = self.state(|| frame_system::Pallet::::block_number()); + if i > current + 1 { + panic!("Jump to future blocks is unsupported in fudge (maybe you've used Blocks::BySecondsFast?)"); + } self.handle.evolve(); } }