From ec5c3028719f8e39c107c58a41719e54439431ae Mon Sep 17 00:00:00 2001 From: lemunozm Date: Mon, 2 Oct 2023 11:02:26 +0200 Subject: [PATCH] proof of concept --- Cargo.lock | 3 + runtime/integration-tests/Cargo.toml | 3 + .../integration-tests/src/experimental/env.rs | 317 ++++++++++++++++++ .../integration-tests/src/experimental/mod.rs | 41 +++ .../src/experimental/runtimes.rs | 82 +++++ .../src/experimental/util.rs | 2 + runtime/integration-tests/src/lib.rs | 24 +- 7 files changed, 449 insertions(+), 23 deletions(-) create mode 100644 runtime/integration-tests/src/experimental/env.rs create mode 100644 runtime/integration-tests/src/experimental/mod.rs create mode 100644 runtime/integration-tests/src/experimental/runtimes.rs create mode 100644 runtime/integration-tests/src/experimental/util.rs diff --git a/Cargo.lock b/Cargo.lock index eb459a289e..40dbc3643b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11109,6 +11109,7 @@ dependencies = [ "pallet-preimage", "pallet-rewards", "pallet-session", + "pallet-timestamp", "pallet-transaction-payment", "pallet-uniques", "pallet-xcm", @@ -11128,6 +11129,7 @@ dependencies = [ "sc-service", "serde", "sp-api", + "sp-block-builder", "sp-consensus-aura", "sp-consensus-babe", "sp-consensus-slots", @@ -11137,6 +11139,7 @@ dependencies = [ "sp-runtime", "sp-std", "sp-tracing", + "sp-transaction-pool", "tokio", "tracing-subscriber", "xcm", diff --git a/runtime/integration-tests/Cargo.toml b/runtime/integration-tests/Cargo.toml index 6ec4036e5c..1946f6ac5e 100644 --- a/runtime/integration-tests/Cargo.toml +++ b/runtime/integration-tests/Cargo.toml @@ -21,6 +21,7 @@ frame-benchmarking = { git = "https://github.com/paritytech/substrate", optional frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } pallet-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.38" } +pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.38" } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } pallet-collective = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } pallet-democracy = { git = "https://github.com/paritytech//substrate", rev = "bcff60a227d455d95b4712b6cb356ce56b1ff672" } @@ -39,6 +40,8 @@ sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "polk sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.38" } sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } +sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } +sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } ## Substrate-Client node-primitives = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } diff --git a/runtime/integration-tests/src/experimental/env.rs b/runtime/integration-tests/src/experimental/env.rs new file mode 100644 index 0000000000..15d2eebcb9 --- /dev/null +++ b/runtime/integration-tests/src/experimental/env.rs @@ -0,0 +1,317 @@ +use std::{ + collections::HashMap, + error::Error, + fmt::Debug, + sync::{Arc, Mutex}, +}; + +use cfg_primitives::{AuraId, BlockNumber, Index}; +use codec::{Decode, Encode}; +use frame_support::traits::GenesisBuild; +use frame_system::EventRecord; +use fudge::{ + digest::{DigestCreator, DigestProvider, FudgeAuraDigest, FudgeBabeDigest}, + inherent::{ + CreateInherentDataProviders, FudgeDummyInherentRelayParachain, FudgeInherentParaParachain, + FudgeInherentTimestamp, + }, + primitives::{Chain, PoolState}, + state::StateProvider, + ParachainBuilder, RelaychainBuilder, TWasmExecutor, +}; +use lazy_static::lazy_static; +use polkadot_core_primitives::Block as RelayBlock; +use polkadot_parachain::primitives::Id as ParaId; +use polkadot_primitives::runtime_api::ParachainHost; +use sc_executor::{WasmExecutionMethod, WasmExecutor}; +use sc_service::{TFullClient, TaskManager}; +use sp_api::ApiExt; +use sp_block_builder::BlockBuilder; +use sp_consensus_babe::digests::CompatibleDigestItem; +use sp_consensus_slots::SlotDuration; +use sp_core::H256; +use sp_runtime::{ + generic::BlockId, + traits::{BlakeTwo256, Block, Extrinsic}, + AccountId32, DigestItem, Storage, +}; +use sp_transaction_pool::runtime_api::TaggedTransactionQueue; +use tokio::runtime::Handle; + +use crate::utils::{logs, time::START_DATE}; + +pub trait Config: + frame_system::Config + + pallet_pool_system::Config< + CurrencyId = CurrencyId, + Balance = Balance, + PoolId = PoolId, + TrancheId = TrancheId, + > + pallet_balances::Config + + pallet_investments::Config + + pallet_pool_registry::Config< + CurrencyId = CurrencyId, + PoolId = PoolId, + Balance = Balance, + ModifyPool = pallet_pool_system::Pallet, + ModifyWriteOffPolicy = pallet_loans::Pallet, + > + pallet_permissions::Config> + + pallet_loans::Config< + Balance = Balance, + PoolId = PoolId, + CollectionId = CollectionId, + ItemId = ItemId, + > + orml_tokens::Config + + orml_asset_registry::Config< + AssetId = CurrencyId, + CustomMetadata = CustomMetadata, + Balance = Balance, + > + pallet_uniques::Config + + pallet_timestamp::Config + + pallet_aura::Config +{ + const KIND: RuntimeKind; +} + +pub type Header = sp_runtime::generic::Header; + +type RelayCidp = Box< + dyn CreateInherentDataProviders< + RelayBlock, + (), + InherentDataProviders = ( + FudgeInherentTimestamp, + sp_consensus_babe::inherents::InherentDataProvider, + FudgeDummyInherentRelayParachain
, + ), + >, +>; + +type RelayDp = Box + Send + Sync>; + +pub enum EventRange { + All, + One(BlockNumber), + Range(BlockNumber, BlockNumber), + Latest, +} + +pub trait Environment { + type RelayRuntime: frame_system::Config + + polkadot_runtime_parachains::paras::Config + + polkadot_runtime_parachains::session_info::Config + + polkadot_runtime_parachains::initializer::Config; + + type RelayApi: BlockBuilder + + ParachainHost + + ApiExt + + TaggedTransactionQueue + + Sync + + Send; + + type RelayChainBuilder; + + const RELAY_CODE: Option<&'static [u8]>; + + type ParachainRuntime: Config; + type ParachainBlock: Block
; + type ParachainChainBuilder; + + const PARA_ID: u32; + + type BuilderError: Error + Debug; + + fn new_relay(relay_storage: Storage) { + sp_tracing::enter_span!(sp_tracing::Level::INFO, "Relay - StartUp"); + let relay_code = Self::RELAY_CODE.expect("Wasm is build. Qed."); + let mut state = StateProvider::new(relay_code); + + state.insert_storage( + polkadot_runtime_parachains::configuration::GenesisConfig::::default() + .build_storage() + .expect("ESSENTIAL: GenesisBuild must not fail at this stage."), + ); + + state.insert_storage( + frame_system::GenesisConfig { + code: relay_code.to_vec(), + } + .build_storage::() + .expect("ESSENTIAL: GenesisBuild must not fail at this stage."), + ); + + state.insert_storage(relay_storage); + + let mut init = fudge::initiator::default::(Handle::current()); + init.with_genesis(Box::new(state)); + + let cidp: fn(Arc<_>) -> RelayCidp = |clone_client: Arc< + TFullClient, + >| { + let instance_id = FudgeInherentTimestamp::create_instance( + std::time::Duration::from_secs(6), + Some(std::time::Duration::from_millis(START_DATE)), + ); + + Box::new(move |parent: H256, ()| { + let client = clone_client.clone(); + let parent_header = client + .header(parent.clone()) + .expect("ESSENTIAL: Relay CIDP must not fail.") + .expect("ESSENTIAL: Relay CIDP must not fail."); + + async move { + let timestamp = FudgeInherentTimestamp::get_instance(instance_id) + .expect("Instances is initialized"); + + let slot = + sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + timestamp.current_time(), + SlotDuration::from_millis(std::time::Duration::from_secs(6).as_millis() as u64), + ); + + let relay_para_inherent = FudgeDummyInherentRelayParachain::new(parent_header); + Ok((timestamp, slot, relay_para_inherent)) + } + }) + }; + + let dp: RelayDp = Box::new(move |parent, inherents| async move { + let babe = FudgeBabeDigest::::new(); + let digest = babe.build_digest(&parent, &inherents).await?; + Ok(digest) + }); + + /* + RelaychainBuilder::<_, _, RelayRt, RelayCidp, RelayDp>::new(init, |client| { + (cidp(client), dp) + }) + */ + } + + fn relay(&self) -> &Self::RelayChainBuilder; + fn relay_with_state_at( + &self, + at: BlockId, + exec: impl FnOnce() -> R, + ) -> Result>; + + fn parachain(&self) -> &Self::ParachainChainBuilder; + fn parachain_with_state_at( + &self, + at: BlockId, + exec: impl FnOnce() -> R, + ) -> Result>; + + fn append_extrinsics( + &mut self, + chain: Chain, + xts: Vec>, + ) -> Result<(), Self::BuilderError> { + for xt in xts { + self.append_extrinsic(chain, xt)?; + } + + Ok(()) + } + + fn append_extrinsic(&mut self, chain: Chain, xt: Vec) -> Result<(), Self::BuilderError>; + + fn with_state( + &self, + chain: Chain, + exec: impl FnOnce() -> R, + ) -> Result; + + fn with_mut_state( + &mut self, + chain: Chain, + exec: impl FnOnce() -> R, + ) -> Result; + + fn evolve(&mut self) -> Result<(), Self::BuilderError>; + + fn events_relay(&self, at: BlockNumber) -> Result>, ()> { + self.relay_with_state_at(BlockId::Number(at), || { + frame_system::Pallet::::events() + }) + .map_err(|_| ()) + .map(|records| records.into_iter().map(|record| record.encode()).collect()) + } + + fn events_parachain(&self, at: BlockNumber) -> Result>, ()> { + self.parachain_with_state_at(BlockId::Number(at), || { + frame_system::Pallet::::events() + }) + .map_err(|_| ()) + .map(|records| records.into_iter().map(|record| record.encode()).collect()) + } + + fn events(&self, chain: Chain, range: EventRange) -> Result>, ()> { + match chain { + Chain::Relay => { + let latest = self + .with_state(chain, || { + frame_system::Pallet::::block_number() + }) + .map_err(|_| ())?; + + match range { + EventRange::Latest => self.events_relay(latest), + EventRange::All => { + let mut events = Vec::new(); + // We MUST NOT query events at genesis block, as this triggers + // a panic. Hence, start at 1. + for block in 1..latest + 1 { + events.extend(self.events_relay(block)?) + } + + Ok(events) + } + EventRange::Range(from, to) => { + let mut events = Vec::new(); + for block in from..to + 1 { + events.extend(self.events_relay(block)?) + } + + Ok(events) + } + EventRange::One(at) => self.events_relay(at), + } + } + Chain::Para(id) => match id { + _ if id == Self::PARA_ID => { + let latest = self + .with_state(chain, || { + frame_system::Pallet::::block_number() + }) + .map_err(|_| ())?; + + match range { + EventRange::Latest => self.events_parachain(latest), + EventRange::All => { + let mut events = Vec::new(); + // We MUST NOT query events at genesis block, as this triggers + // a panic. Hence, start at 1. + for block in 1..latest + 1 { + events.extend(self.events_parachain(block)?) + } + + Ok(events) + } + EventRange::Range(from, to) => { + let mut events = Vec::new(); + for block in from..to + 1 { + events.extend(self.events_parachain(block)?) + } + + Ok(events) + } + EventRange::One(at) => self.events_parachain(at), + } + } + _ => Err(()), + }, + } + } +} diff --git a/runtime/integration-tests/src/experimental/mod.rs b/runtime/integration-tests/src/experimental/mod.rs new file mode 100644 index 0000000000..a2d831f6e0 --- /dev/null +++ b/runtime/integration-tests/src/experimental/mod.rs @@ -0,0 +1,41 @@ +use cfg_primitives::{Balance, BlockNumber, CollectionId, ItemId, Moment, PoolId, TrancheId}; +use cfg_types::{ + permissions::{PermissionScope, Role}, + tokens::{CurrencyId, CustomMetadata, TrancheCurrency}, +}; +use fudge::primitives::Chain; +use polkadot_core_primitives::Block as RelayBlock; +use polkadot_primitives::runtime_api::ParachainHost; +use sp_api::ApiExt; +use sp_block_builder::BlockBuilder; +use sp_runtime::AccountId32; +use sp_transaction_pool::runtime_api::TaggedTransactionQueue; + +pub mod env; +pub mod util; + +#[macro_export] +macro_rules! test_with_all_runtimes { + ($setup:ident, $name:ident) => { + mod $name { + use super::*; + + #[test] + fn development() { + $setup::() + .execute_with($name::); + } + + #[test] + fn altair() { + $setup::().execute_with($name::); + } + + #[test] + fn centrifuge() { + $setup::() + .execute_with($name::); + } + } + }; +} diff --git a/runtime/integration-tests/src/experimental/runtimes.rs b/runtime/integration-tests/src/experimental/runtimes.rs new file mode 100644 index 0000000000..9c458fb591 --- /dev/null +++ b/runtime/integration-tests/src/experimental/runtimes.rs @@ -0,0 +1,82 @@ +pub enum RuntimeKind { + Development, + Altair, + Centrifuge, +} + +// --------------------------------- + +#[fudge::companion] +pub struct CentrifugeEnv { + #[fudge::relaychain] + pub relay: RelaychainBuilder, + #[fudge::parachain(PARA_ID)] + pub parachain: ParachainBuilder, + nonce_manager: Arc>, + pub events: Arc>, +} + +impl Environment for CentrifugeEnv { + // TODO... + // implement non-default methods of Environment trait +} + +impl Config for centrifuge_runtime::Runtime { + //type RelayApi = polkadot_runtime::RuntimeApi; + //type RelayRuntime = polkadot_runtime::Runtime; + + const KIND: RuntimeKind = RuntimeKind::Centrifuge; +} + +// --------------------------------- + +#[fudge::companion] +pub struct AltairEnv { + #[fudge::relaychain] + pub relay: RelaychainBuilder, + #[fudge::parachain(PARA_ID)] + pub parachain: ParachainBuilder, + nonce_manager: Arc>, + pub events: Arc>, +} + +impl Environment for AltairEnv { + // TODO... + // implement non-default methods of Environment trait +} + +impl Config for altair_runtime::Runtime { + //type RelayApi = kusama_runtime::RuntimeApi; + //type RelayRuntime = kusama_runtime::Runtime; + + const KIND: RuntimeKind = RuntimeKind::Altair; +} + +// --------------------------------- + +#[fudge::companion] +pub struct DevelopmentEnv { + #[fudge::relaychain] + pub relay: RelaychainBuilder, + #[fudge::parachain(PARA_ID)] + pub parachain: + ParachainBuilder, + nonce_manager: Arc>, + pub events: Arc>, +} + +impl Environment for DevelopmentEnv { + // TODO... + // implement non-default methods of Environment trait +} + +impl Config for development_runtime::Runtime { + //type RelayApi = rococo_runtime::RuntimeApi; + //type RelayRuntime = rococo_runtime::Runtime; + + const KIND: RuntimeKind = RuntimeKind::Development; +} + + +} + diff --git a/runtime/integration-tests/src/experimental/util.rs b/runtime/integration-tests/src/experimental/util.rs new file mode 100644 index 0000000000..7e1d516357 --- /dev/null +++ b/runtime/integration-tests/src/experimental/util.rs @@ -0,0 +1,2 @@ +#[test] +fn foo() {} diff --git a/runtime/integration-tests/src/lib.rs b/runtime/integration-tests/src/lib.rs index 25636495d4..a4f9d85d1d 100644 --- a/runtime/integration-tests/src/lib.rs +++ b/runtime/integration-tests/src/lib.rs @@ -15,6 +15,7 @@ #![allow(unused)] mod evm; +mod experimental; mod liquidity_pools; mod pools; mod rewards; @@ -26,26 +27,8 @@ mod utils; /// in order to get the right stuff from the respective runtime. mod chain { pub mod centrifuge { - #[cfg(feature = "runtime-altair")] - pub use altair::*; - #[cfg(feature = "runtime-centrifuge")] - pub use centrifuge::*; - #[cfg(feature = "runtime-development")] pub use development::*; - #[cfg(feature = "runtime-centrifuge")] - pub mod centrifuge { - pub use centrifuge_runtime::*; - pub const PARA_ID: u32 = 2031; - } - - #[cfg(feature = "runtime-altair")] - pub mod altair { - pub use altair_runtime::*; - pub const PARA_ID: u32 = 2088; - } - - #[cfg(feature = "runtime-development")] pub mod development { pub use development_runtime::*; pub const PARA_ID: u32 = 2000; @@ -53,11 +36,6 @@ mod chain { } pub mod relay { - #[cfg(feature = "runtime-altair")] - pub use kusama_runtime::*; - #[cfg(feature = "runtime-centrifuge")] - pub use polkadot_runtime::*; - #[cfg(feature = "runtime-development")] pub use rococo_runtime::*; } }