From fa7c0531b64856c0f9f585a09b2d78e1f9372b78 Mon Sep 17 00:00:00 2001 From: Dariusz Depta Date: Tue, 28 Nov 2023 13:59:09 +0100 Subject: [PATCH 1/9] Initial version. --- src/app.rs | 64 ++++++++++++++++-------- src/app_builder.rs | 111 ++++++++++++++++++++++++++++++++++++------ src/lib.rs | 1 + src/staking.rs | 3 ++ src/stargate.rs | 60 +++++++++++++++++++++++ src/tests/test_app.rs | 4 +- src/wasm.rs | 3 ++ 7 files changed, 208 insertions(+), 38 deletions(-) create mode 100644 src/stargate.rs diff --git a/src/app.rs b/src/app.rs index 5c913275..91e886b4 100644 --- a/src/app.rs +++ b/src/app.rs @@ -6,6 +6,7 @@ use crate::gov::Gov; use crate::ibc::Ibc; use crate::module::{FailingModule, Module}; use crate::staking::{Distribution, DistributionKeeper, StakeKeeper, Staking, StakingSudo}; +use crate::stargate::{Stargate, StargateFailing}; use crate::transactions::transactional; use crate::wasm::{ContractData, Wasm, WasmKeeper, WasmSudo}; use crate::{AppBuilder, GovFailingModule, IbcFailingModule}; @@ -36,6 +37,7 @@ pub type BasicApp = App< DistributionKeeper, IbcFailingModule, GovFailingModule, + StargateFailing, >; /// Router is a persisted state. You can query this. @@ -52,16 +54,17 @@ pub struct App< Distr = DistributionKeeper, Ibc = IbcFailingModule, Gov = GovFailingModule, + Stargate = StargateFailing, > { - pub(crate) router: Router, + pub(crate) router: Router, pub(crate) api: Api, pub(crate) storage: Storage, pub(crate) block: BlockInfo, } /// No-op application initialization function. -pub fn no_init( - router: &mut Router, +pub fn no_init( + router: &mut Router, api: &dyn Api, storage: &mut dyn Storage, ) { @@ -87,6 +90,7 @@ impl BasicApp { DistributionKeeper, IbcFailingModule, GovFailingModule, + StargateFailing, >, &dyn Api, &mut dyn Storage, @@ -111,6 +115,7 @@ where DistributionKeeper, IbcFailingModule, GovFailingModule, + StargateFailing, >, &dyn Api, &mut dyn Storage, @@ -119,8 +124,8 @@ where AppBuilder::new_custom().build(init_fn) } -impl Querier - for App +impl Querier + for App where CustomT::ExecT: Clone + Debug + PartialEq + JsonSchema + DeserializeOwned + 'static, CustomT::QueryT: CustomQuery + DeserializeOwned + 'static, @@ -133,6 +138,7 @@ where DistrT: Distribution, IbcT: Ibc, GovT: Gov, + StargateT: Stargate, { fn raw_query(&self, bin_request: &[u8]) -> QuerierResult { self.router @@ -141,8 +147,9 @@ where } } -impl Executor - for App +impl + Executor + for App where CustomT::ExecT: Clone + Debug + PartialEq + JsonSchema + DeserializeOwned + 'static, CustomT::QueryT: CustomQuery + DeserializeOwned + 'static, @@ -155,6 +162,7 @@ where DistrT: Distribution, IbcT: Ibc, GovT: Gov, + StargateT: Stargate, { fn execute(&mut self, sender: Addr, msg: CosmosMsg) -> AnyResult { let mut all = self.execute_multi(sender, vec![msg])?; @@ -163,8 +171,8 @@ where } } -impl - App +impl + App where WasmT: Wasm, BankT: Bank, @@ -175,9 +183,12 @@ where DistrT: Distribution, IbcT: Ibc, GovT: Gov, + StargateT: Stargate, { /// Returns a shared reference to application's router. - pub fn router(&self) -> &Router { + pub fn router( + &self, + ) -> &Router { &self.router } @@ -199,7 +210,7 @@ where pub fn init_modules(&mut self, init_fn: F) -> T where F: FnOnce( - &mut Router, + &mut Router, &dyn Api, &mut dyn Storage, ) -> T, @@ -210,7 +221,7 @@ where pub fn read_module(&self, query_fn: F) -> T where F: FnOnce( - &Router, + &Router, &dyn Api, &dyn Storage, ) -> T, @@ -221,8 +232,8 @@ where // Helper functions to call some custom WasmKeeper logic. // They show how we can easily add such calls to other custom keepers (CustomT, StakingT, etc) -impl - App +impl + App where BankT: Bank, ApiT: Api, @@ -233,6 +244,7 @@ where DistrT: Distribution, IbcT: Ibc, GovT: Gov, + StargateT: Stargate, CustomT::ExecT: Clone + Debug + PartialEq + JsonSchema + DeserializeOwned + 'static, CustomT::QueryT: CustomQuery + DeserializeOwned + 'static, { @@ -320,8 +332,8 @@ where } } -impl - App +impl + App where CustomT::ExecT: Debug + PartialEq + Clone + JsonSchema + DeserializeOwned + 'static, CustomT::QueryT: CustomQuery + DeserializeOwned + 'static, @@ -334,6 +346,7 @@ where DistrT: Distribution, IbcT: Ibc, GovT: Gov, + StargateT: Stargate, { pub fn set_block(&mut self, block: BlockInfo) { self.router @@ -434,7 +447,7 @@ where } #[derive(Clone)] -pub struct Router { +pub struct Router { // this can remain crate-only as all special functions are wired up to app currently // we need to figure out another format for wasm, as some like sudo need to be called after init pub(crate) wasm: Wasm, @@ -445,10 +458,11 @@ pub struct Router { pub distribution: Distr, pub ibc: Ibc, pub gov: Gov, + pub stargate: Stargate, } -impl - Router +impl + Router where CustomT::ExecT: Clone + Debug + PartialEq + JsonSchema + DeserializeOwned + 'static, CustomT::QueryT: CustomQuery + DeserializeOwned + 'static, @@ -459,6 +473,7 @@ where DistrT: Distribution, IbcT: Ibc, GovT: Gov, + StargateT: Stargate, { pub fn querier<'a>( &'a self, @@ -532,8 +547,8 @@ pub trait CosmosRouter { ) -> AnyResult; } -impl CosmosRouter - for Router +impl CosmosRouter + for Router where CustomT::ExecT: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static, CustomT::QueryT: CustomQuery + DeserializeOwned + 'static, @@ -544,6 +559,7 @@ where DistrT: Distribution, IbcT: Ibc, GovT: Gov, + StargateT: Stargate, { type ExecC = CustomT::ExecT; type QueryC = CustomT::QueryT; @@ -566,6 +582,9 @@ where .execute(api, storage, self, block, sender, msg), CosmosMsg::Ibc(msg) => self.ibc.execute(api, storage, self, block, sender, msg), CosmosMsg::Gov(msg) => self.gov.execute(api, storage, self, block, sender, msg), + CosmosMsg::Stargate { type_url, value } => self + .stargate + .execute(api, storage, self, block, sender, type_url, value), _ => bail!("Cannot execute {:?}", msg), } } @@ -587,6 +606,9 @@ where QueryRequest::Custom(req) => self.custom.query(api, storage, &querier, block, req), QueryRequest::Staking(req) => self.staking.query(api, storage, &querier, block, req), QueryRequest::Ibc(req) => self.ibc.query(api, storage, &querier, block, req), + QueryRequest::Stargate { path, data } => self + .stargate + .query(api, storage, &querier, block, path, data), _ => unimplemented!(), } } diff --git a/src/app_builder.rs b/src/app_builder.rs index 8e9e738c..4b2f4b33 100644 --- a/src/app_builder.rs +++ b/src/app_builder.rs @@ -1,5 +1,6 @@ //! Implementation of the builder for [App]. +use crate::stargate::{Stargate, StargateFailing}; use crate::{ App, Bank, BankKeeper, Distribution, DistributionKeeper, FailingModule, Gov, GovFailingModule, Ibc, IbcFailingModule, Module, Router, StakeKeeper, Staking, Wasm, WasmKeeper, @@ -35,11 +36,12 @@ pub type BasicAppBuilder = AppBuilder< DistributionKeeper, IbcFailingModule, GovFailingModule, + StargateFailing, >; /// Utility to build [App] in stages. /// When particular properties are not explicitly set, then default values are used. -pub struct AppBuilder { +pub struct AppBuilder { api: Api, block: BlockInfo, storage: Storage, @@ -50,6 +52,7 @@ pub struct AppBuilder { fn default() -> Self { @@ -81,6 +85,7 @@ impl DistributionKeeper, IbcFailingModule, GovFailingModule, + StargateFailing, > { /// Creates builder with default components working with empty exec and query messages. @@ -96,6 +101,7 @@ impl distribution: DistributionKeeper::new(), ibc: IbcFailingModule::new(), gov: GovFailingModule::new(), + stargate: StargateFailing, } } } @@ -111,6 +117,7 @@ impl DistributionKeeper, IbcFailingModule, GovFailingModule, + StargateFailing, > where ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static, @@ -130,12 +137,13 @@ where distribution: DistributionKeeper::new(), ibc: IbcFailingModule::new(), gov: GovFailingModule::new(), + stargate: StargateFailing, } } } -impl - AppBuilder +impl + AppBuilder where CustomT: Module, WasmT: Wasm, @@ -148,7 +156,8 @@ where pub fn with_wasm>( self, wasm: NewWasm, - ) -> AppBuilder { + ) -> AppBuilder + { let AppBuilder { bank, api, @@ -159,6 +168,7 @@ where distribution, ibc, gov, + stargate, .. } = self; @@ -173,6 +183,7 @@ where distribution, ibc, gov, + stargate, } } @@ -180,7 +191,8 @@ where pub fn with_bank( self, bank: NewBank, - ) -> AppBuilder { + ) -> AppBuilder + { let AppBuilder { wasm, api, @@ -191,6 +203,7 @@ where distribution, ibc, gov, + stargate, .. } = self; @@ -205,6 +218,7 @@ where distribution, ibc, gov, + stargate, } } @@ -212,7 +226,8 @@ where pub fn with_api( self, api: NewApi, - ) -> AppBuilder { + ) -> AppBuilder + { let AppBuilder { wasm, bank, @@ -223,6 +238,7 @@ where distribution, ibc, gov, + stargate, .. } = self; @@ -237,6 +253,7 @@ where distribution, ibc, gov, + stargate, } } @@ -244,7 +261,8 @@ where pub fn with_storage( self, storage: NewStorage, - ) -> AppBuilder { + ) -> AppBuilder + { let AppBuilder { wasm, api, @@ -255,6 +273,7 @@ where distribution, ibc, gov, + stargate, .. } = self; @@ -269,6 +288,7 @@ where distribution, ibc, gov, + stargate, } } @@ -280,7 +300,8 @@ where pub fn with_custom( self, custom: NewCustom, - ) -> AppBuilder { + ) -> AppBuilder + { let AppBuilder { wasm, bank, @@ -291,6 +312,7 @@ where distribution, ibc, gov, + stargate, .. } = self; @@ -305,6 +327,7 @@ where distribution, ibc, gov, + stargate, } } @@ -312,7 +335,8 @@ where pub fn with_staking( self, staking: NewStaking, - ) -> AppBuilder { + ) -> AppBuilder + { let AppBuilder { wasm, api, @@ -323,6 +347,7 @@ where distribution, ibc, gov, + stargate, .. } = self; @@ -337,6 +362,7 @@ where distribution, ibc, gov, + stargate, } } @@ -344,8 +370,18 @@ where pub fn with_distribution( self, distribution: NewDistribution, - ) -> AppBuilder - { + ) -> AppBuilder< + BankT, + ApiT, + StorageT, + CustomT, + WasmT, + StakingT, + NewDistribution, + IbcT, + GovT, + StargateT, + > { let AppBuilder { wasm, api, @@ -356,6 +392,7 @@ where bank, ibc, gov, + stargate, .. } = self; @@ -370,6 +407,7 @@ where distribution, ibc, gov, + stargate, } } @@ -383,7 +421,8 @@ where pub fn with_ibc( self, ibc: NewIbc, - ) -> AppBuilder { + ) -> AppBuilder + { let AppBuilder { wasm, api, @@ -394,6 +433,7 @@ where bank, distribution, gov, + stargate, .. } = self; @@ -408,6 +448,7 @@ where distribution, ibc, gov, + stargate, } } @@ -415,7 +456,8 @@ where pub fn with_gov( self, gov: NewGov, - ) -> AppBuilder { + ) -> AppBuilder + { let AppBuilder { wasm, api, @@ -426,6 +468,42 @@ where bank, distribution, ibc, + stargate, + .. + } = self; + + AppBuilder { + api, + block, + storage, + bank, + wasm, + custom, + staking, + distribution, + ibc, + gov, + stargate, + } + } + + /// Overwrites the default stargate interface. + pub fn with_stargate( + self, + stargate: NewStargate, + ) -> AppBuilder + { + let AppBuilder { + wasm, + api, + storage, + custom, + block, + staking, + bank, + distribution, + ibc, + gov, .. } = self; @@ -440,6 +518,7 @@ where distribution, ibc, gov, + stargate, } } @@ -455,7 +534,7 @@ where pub fn build( self, init_fn: F, - ) -> App + ) -> App where BankT: Bank, ApiT: Api, @@ -466,8 +545,9 @@ where DistrT: Distribution, IbcT: Ibc, GovT: Gov, + StargateT: Stargate, F: FnOnce( - &mut Router, + &mut Router, &dyn Api, &mut dyn Storage, ), @@ -480,6 +560,7 @@ where distribution: self.distribution, ibc: self.ibc, gov: self.gov, + stargate: self.stargate, }; let mut app = App { diff --git a/src/lib.rs b/src/lib.rs index e30c2185..ab37cceb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,6 +22,7 @@ mod ibc; mod module; mod prefixed_storage; mod staking; +mod stargate; mod test_helpers; mod tests; mod transactions; diff --git a/src/staking.rs b/src/staking.rs index 5155c672..f92d056d 100644 --- a/src/staking.rs +++ b/src/staking.rs @@ -1015,6 +1015,7 @@ impl Module for DistributionKeeper { #[cfg(test)] mod test { use super::*; + use crate::stargate::StargateFailing; use crate::{ app::MockRouter, BankKeeper, FailingModule, GovFailingModule, IbcFailingModule, Router, WasmKeeper, @@ -1034,6 +1035,7 @@ mod test { DistributionKeeper, IbcFailingModule, GovFailingModule, + StargateFailing, >; fn mock_router() -> BasicRouter { @@ -1045,6 +1047,7 @@ mod test { distribution: DistributionKeeper::new(), ibc: IbcFailingModule::new(), gov: GovFailingModule::new(), + stargate: StargateFailing, } } diff --git a/src/stargate.rs b/src/stargate.rs new file mode 100644 index 00000000..dc8ee592 --- /dev/null +++ b/src/stargate.rs @@ -0,0 +1,60 @@ +//! add-docs + +use crate::error::AnyResult; +use crate::{AppResponse, CosmosRouter}; +use anyhow::bail; +use cosmwasm_std::{Addr, Api, Binary, BlockInfo, CustomQuery, Querier, Storage}; +use schemars::JsonSchema; +use serde::de::DeserializeOwned; +use std::fmt::Debug; + +/// Stargate interface. +pub trait Stargate { + /// Processes stargate messages. + fn execute( + &self, + api: &dyn Api, + storage: &mut dyn Storage, + router: &dyn CosmosRouter, + block: &BlockInfo, + sender: Addr, + type_url: String, + value: Binary, + ) -> AnyResult + where + ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static, + QueryC: CustomQuery + DeserializeOwned + 'static, + { + let _ = (api, storage, router, block); + bail!( + "Unexpected stargate message: (type_ur = {}, value = {:?}) from {:?}", + type_url, + value, + sender + ) + } + + /// Processes stargate queries. + fn query( + &self, + api: &dyn Api, + storage: &dyn Storage, + querier: &dyn Querier, + block: &BlockInfo, + path: String, + data: Binary, + ) -> AnyResult { + let _ = (api, storage, querier, block); + bail!( + "Unexpected stargate query: path = {:?}, data = {:?}", + path, + data + ) + } +} + +/// Always failing stargate mock implementation. +#[derive(Default)] +pub struct StargateFailing; + +impl Stargate for StargateFailing {} diff --git a/src/tests/test_app.rs b/src/tests/test_app.rs index 8e19e3da..f6d41f18 100644 --- a/src/tests/test_app.rs +++ b/src/tests/test_app.rs @@ -39,8 +39,8 @@ where app.wrap().query_all_balances(addr).unwrap() } -fn query_router( - router: &Router, +fn query_router( + router: &Router, api: &dyn Api, storage: &dyn Storage, rcpt: &Addr, diff --git a/src/wasm.rs b/src/wasm.rs index 4e7fe130..c2debac2 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -1117,6 +1117,7 @@ mod test { use crate::bank::BankKeeper; use crate::module::FailingModule; use crate::staking::{DistributionKeeper, StakeKeeper}; + use crate::stargate::StargateFailing; use crate::test_helpers::{caller, error, payout}; use crate::transactions::StorageTransaction; use crate::{GovFailingModule, IbcFailingModule}; @@ -1135,6 +1136,7 @@ mod test { DistributionKeeper, IbcFailingModule, GovFailingModule, + StargateFailing, >; fn wasm_keeper() -> WasmKeeper { @@ -1150,6 +1152,7 @@ mod test { distribution: DistributionKeeper::new(), ibc: IbcFailingModule::new(), gov: GovFailingModule::new(), + stargate: StargateFailing, } } From a7223d13a546b125e6df6c0bb4ffe5617161be21 Mon Sep 17 00:00:00 2001 From: Dariusz Depta Date: Tue, 28 Nov 2023 15:45:28 +0100 Subject: [PATCH 2/9] Added tests. --- src/lib.rs | 1 + src/stargate.rs | 79 ++++++++++++++++- tests/test_app_builder/mod.rs | 1 + tests/test_app_builder/test_with_stargate.rs | 93 ++++++++++++++++++++ 4 files changed, 172 insertions(+), 2 deletions(-) create mode 100644 tests/test_app_builder/test_with_stargate.rs diff --git a/src/lib.rs b/src/lib.rs index ab37cceb..7f44d300 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,4 +43,5 @@ pub use crate::module::{AcceptingModule, FailingModule, Module}; pub use crate::staking::{ Distribution, DistributionKeeper, StakeKeeper, Staking, StakingInfo, StakingSudo, }; +pub use crate::stargate::{Stargate, StargateAccepting, StargateFailing}; pub use crate::wasm::{ContractData, Wasm, WasmKeeper, WasmSudo}; diff --git a/src/stargate.rs b/src/stargate.rs index dc8ee592..610ed25e 100644 --- a/src/stargate.rs +++ b/src/stargate.rs @@ -54,7 +54,82 @@ pub trait Stargate { } /// Always failing stargate mock implementation. -#[derive(Default)] pub struct StargateFailing; -impl Stargate for StargateFailing {} +impl Stargate for StargateFailing { + /// Rejects all stargate messages. + fn execute( + &self, + _api: &dyn Api, + _storage: &mut dyn Storage, + _router: &dyn CosmosRouter, + _block: &BlockInfo, + sender: Addr, + type_url: String, + value: Binary, + ) -> AnyResult + where + ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static, + QueryC: CustomQuery + DeserializeOwned + 'static, + { + bail!( + "Unexpected stargate message: (type_ur = {}, value = {:?}) from {:?}", + type_url, + value, + sender + ) + } + + /// Rejects stargate queries. + fn query( + &self, + _api: &dyn Api, + _storage: &dyn Storage, + _querier: &dyn Querier, + _block: &BlockInfo, + path: String, + data: Binary, + ) -> AnyResult { + bail!( + "Unexpected stargate query: path = {:?}, data = {:?}", + path, + data + ) + } +} + +/// Always accepting stargate mock implementation. +pub struct StargateAccepting; + +impl Stargate for StargateAccepting { + /// Accepts all stargate messages. + fn execute( + &self, + _api: &dyn Api, + _storage: &mut dyn Storage, + _router: &dyn CosmosRouter, + _block: &BlockInfo, + _sender: Addr, + _type_url: String, + _value: Binary, + ) -> AnyResult + where + ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static, + QueryC: CustomQuery + DeserializeOwned + 'static, + { + Ok(AppResponse::default()) + } + + /// Accepts all stargate queries. + fn query( + &self, + _api: &dyn Api, + _storage: &dyn Storage, + _querier: &dyn Querier, + _block: &BlockInfo, + _path: String, + _data: Binary, + ) -> AnyResult { + Ok(Binary::default()) + } +} diff --git a/tests/test_app_builder/mod.rs b/tests/test_app_builder/mod.rs index 2a2412ee..476df228 100644 --- a/tests/test_app_builder/mod.rs +++ b/tests/test_app_builder/mod.rs @@ -13,6 +13,7 @@ mod test_with_distribution; mod test_with_gov; mod test_with_ibc; mod test_with_staking; +mod test_with_stargate; mod test_with_storage; mod test_with_wasm; diff --git a/tests/test_app_builder/test_with_stargate.rs b/tests/test_app_builder/test_with_stargate.rs new file mode 100644 index 00000000..18276366 --- /dev/null +++ b/tests/test_app_builder/test_with_stargate.rs @@ -0,0 +1,93 @@ +use anyhow::bail; +use cosmwasm_std::{ + to_json_vec, Addr, Api, Binary, BlockInfo, CosmosMsg, CustomQuery, Empty, Querier, + QueryRequest, Storage, +}; +use cw_multi_test::error::AnyResult; +use cw_multi_test::{AppBuilder, AppResponse, CosmosRouter, Executor, Stargate}; +use schemars::JsonSchema; +use serde::de::DeserializeOwned; +use std::fmt::Debug; + +const EXECUTE_MSG: &str = "stargate execute called"; +const QUERY_MSG: &str = "stargate query called"; + +struct MyStargateKeeper; + +impl Stargate for MyStargateKeeper { + /// Custom processing of stargate messages. + fn execute( + &self, + _api: &dyn Api, + _storage: &mut dyn Storage, + _router: &dyn CosmosRouter, + _block: &BlockInfo, + _sender: Addr, + type_url: String, + value: Binary, + ) -> AnyResult + where + ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static, + QueryC: CustomQuery + DeserializeOwned + 'static, + { + assert_eq!("test", type_url); + assert_eq!(Binary::default(), value); + bail!(EXECUTE_MSG); + } + + /// Custom stargate queries. + fn query( + &self, + _api: &dyn Api, + _storage: &dyn Storage, + _querier: &dyn Querier, + _block: &BlockInfo, + path: String, + data: Binary, + ) -> AnyResult { + assert_eq!("test", path); + assert_eq!(Binary::default(), data); + bail!(QUERY_MSG); + } +} + +#[test] +fn building_app_with_custom_stargate_should_work() { + // build custom stargate keeper + let stargate_keeper = MyStargateKeeper; + + // build the application with custom stargate keeper + let app_builder = AppBuilder::default(); + let mut app = app_builder + .with_stargate(stargate_keeper) + .build(|_, _, _| {}); + + // executing stargate message should return + // an error defined in custom stargate keeper + assert_eq!( + app.execute( + Addr::unchecked("sender"), + CosmosMsg::Stargate { + type_url: "test".to_string(), + value: Default::default() + }, + ) + .unwrap_err() + .to_string(), + EXECUTE_MSG, + ); + + // executing stargate query should return + // an error defined in custom stargate keeper + let query: QueryRequest = QueryRequest::Stargate { + path: "test".to_string(), + data: Default::default(), + }; + assert_eq!( + app.wrap() + .raw_query(to_json_vec(&query).unwrap().as_slice()) + .unwrap() + .unwrap_err(), + QUERY_MSG + ); +} From a5fdbe7c2440d0eb87111bf31f86029a0aee819f Mon Sep 17 00:00:00 2001 From: Dariusz Depta Date: Tue, 28 Nov 2023 16:25:21 +0100 Subject: [PATCH 3/9] Added tests. --- src/stargate.rs | 20 +------- tests/test_app_builder/test_with_stargate.rs | 54 +++++++++++++++++++- 2 files changed, 55 insertions(+), 19 deletions(-) diff --git a/src/stargate.rs b/src/stargate.rs index 610ed25e..657ab63c 100644 --- a/src/stargate.rs +++ b/src/stargate.rs @@ -23,16 +23,7 @@ pub trait Stargate { ) -> AnyResult where ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static, - QueryC: CustomQuery + DeserializeOwned + 'static, - { - let _ = (api, storage, router, block); - bail!( - "Unexpected stargate message: (type_ur = {}, value = {:?}) from {:?}", - type_url, - value, - sender - ) - } + QueryC: CustomQuery + DeserializeOwned + 'static; /// Processes stargate queries. fn query( @@ -43,14 +34,7 @@ pub trait Stargate { block: &BlockInfo, path: String, data: Binary, - ) -> AnyResult { - let _ = (api, storage, querier, block); - bail!( - "Unexpected stargate query: path = {:?}, data = {:?}", - path, - data - ) - } + ) -> AnyResult; } /// Always failing stargate mock implementation. diff --git a/tests/test_app_builder/test_with_stargate.rs b/tests/test_app_builder/test_with_stargate.rs index 18276366..fb668557 100644 --- a/tests/test_app_builder/test_with_stargate.rs +++ b/tests/test_app_builder/test_with_stargate.rs @@ -4,7 +4,9 @@ use cosmwasm_std::{ QueryRequest, Storage, }; use cw_multi_test::error::AnyResult; -use cw_multi_test::{AppBuilder, AppResponse, CosmosRouter, Executor, Stargate}; +use cw_multi_test::{ + AppBuilder, AppResponse, CosmosRouter, Executor, Stargate, StargateAccepting, StargateFailing, +}; use schemars::JsonSchema; use serde::de::DeserializeOwned; use std::fmt::Debug; @@ -91,3 +93,53 @@ fn building_app_with_custom_stargate_should_work() { QUERY_MSG ); } + +#[test] +fn building_app_with_accepting_stargate_should_work() { + let app_builder = AppBuilder::default(); + let mut app = app_builder + .with_stargate(StargateAccepting) + .build(|_, _, _| {}); + + app.execute( + Addr::unchecked("sender"), + CosmosMsg::Stargate { + type_url: "test".to_string(), + value: Default::default(), + }, + ) + .unwrap(); + + let _ = app + .wrap() + .query::(&QueryRequest::Stargate { + path: "test".to_string(), + data: Default::default(), + }) + .is_ok(); +} + +#[test] +fn building_app_with_failing_stargate_should_work() { + let app_builder = AppBuilder::default(); + let mut app = app_builder + .with_stargate(StargateFailing) + .build(|_, _, _| {}); + + app.execute( + Addr::unchecked("sender"), + CosmosMsg::Stargate { + type_url: "test".to_string(), + value: Default::default(), + }, + ) + .unwrap_err(); + + let _ = app + .wrap() + .query::(&QueryRequest::Stargate { + path: "test".to_string(), + data: Default::default(), + }) + .unwrap_err(); +} From b866413a4113464f9a1f5229b102f946517d6bde Mon Sep 17 00:00:00 2001 From: Dariusz Depta Date: Wed, 29 Nov 2023 10:36:39 +0100 Subject: [PATCH 4/9] Added tests. --- src/stargate.rs | 48 ++++++++----------------------- src/test_helpers/stargate.rs | 24 ++++++++++++++++ src/tests/mod.rs | 1 + src/tests/test_stargate.rs | 56 ++++++++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 36 deletions(-) create mode 100644 src/test_helpers/stargate.rs create mode 100644 src/tests/test_stargate.rs diff --git a/src/stargate.rs b/src/stargate.rs index 657ab63c..23b26f31 100644 --- a/src/stargate.rs +++ b/src/stargate.rs @@ -21,41 +21,11 @@ pub trait Stargate { type_url: String, value: Binary, ) -> AnyResult - where - ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static, - QueryC: CustomQuery + DeserializeOwned + 'static; - - /// Processes stargate queries. - fn query( - &self, - api: &dyn Api, - storage: &dyn Storage, - querier: &dyn Querier, - block: &BlockInfo, - path: String, - data: Binary, - ) -> AnyResult; -} - -/// Always failing stargate mock implementation. -pub struct StargateFailing; - -impl Stargate for StargateFailing { - /// Rejects all stargate messages. - fn execute( - &self, - _api: &dyn Api, - _storage: &mut dyn Storage, - _router: &dyn CosmosRouter, - _block: &BlockInfo, - sender: Addr, - type_url: String, - value: Binary, - ) -> AnyResult where ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static, QueryC: CustomQuery + DeserializeOwned + 'static, { + let _ = (api, storage, router, block); bail!( "Unexpected stargate message: (type_ur = {}, value = {:?}) from {:?}", type_url, @@ -64,16 +34,17 @@ impl Stargate for StargateFailing { ) } - /// Rejects stargate queries. + /// Processes stargate queries. fn query( &self, - _api: &dyn Api, - _storage: &dyn Storage, - _querier: &dyn Querier, - _block: &BlockInfo, + api: &dyn Api, + storage: &dyn Storage, + querier: &dyn Querier, + block: &BlockInfo, path: String, data: Binary, ) -> AnyResult { + let _ = (api, storage, querier, block); bail!( "Unexpected stargate query: path = {:?}, data = {:?}", path, @@ -82,6 +53,11 @@ impl Stargate for StargateFailing { } } +/// Always failing stargate mock implementation. +pub struct StargateFailing; + +impl Stargate for StargateFailing {} + /// Always accepting stargate mock implementation. pub struct StargateAccepting; diff --git a/src/test_helpers/stargate.rs b/src/test_helpers/stargate.rs new file mode 100644 index 00000000..ca090e75 --- /dev/null +++ b/src/test_helpers/stargate.rs @@ -0,0 +1,24 @@ +use crate::{Contract, ContractWrapper}; +use cosmwasm_std::{ + Binary, CosmosMsg, Deps, DepsMut, Empty, Env, MessageInfo, Response, StdResult, +}; + +fn instantiate(_deps: DepsMut, _env: Env, _info: MessageInfo, _msg: Empty) -> StdResult { + Ok(Response::new()) +} + +fn execute(_deps: DepsMut, _env: Env, _info: MessageInfo, _msg: Empty) -> StdResult { + Ok(Response::new().add_message(CosmosMsg::Stargate { + type_url: "/this.is.a.stargate.test.helper".to_string(), + value: Default::default(), + })) +} + +fn query(_deps: Deps, _env: Env, _msg: Empty) -> StdResult { + Ok(Binary::default()) +} + +pub fn contract() -> Box> { + let contract = ContractWrapper::new(execute, instantiate, query); + Box::new(contract) +} diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 2a190c34..53370229 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -4,3 +4,4 @@ mod test_app; mod test_custom_handler; mod test_gov; mod test_ibc; +mod test_stargate; diff --git a/src/tests/test_stargate.rs b/src/tests/test_stargate.rs new file mode 100644 index 00000000..47464e04 --- /dev/null +++ b/src/tests/test_stargate.rs @@ -0,0 +1,56 @@ +use crate::test_helpers::stargate; +use crate::{no_init, App, AppBuilder, Executor, StargateAccepting}; +use cosmwasm_std::Empty; + +#[test] +fn default_stargate() { + let mut app = App::default(); + + // store the contract + let creator_addr = app.api().addr_make("creator"); + let code = app.store_code_with_creator(creator_addr, stargate::contract()); + + // instantiate contract + let owner_addr = app.api().addr_make("owner"); + let contract_addr = app + .instantiate_contract(code, owner_addr, &Empty {}, &[], "tauri", None) + .unwrap(); + + // execute empty message on the contract, this contract returns stargate message + // which is rejected by default failing stargate keeper + let sender_addr = app.api().addr_make("sender"); + let err = app + .execute_contract(sender_addr, contract_addr, &Empty {}, &[]) + .unwrap_err(); + + // source error message comes from failing stargate keeper + assert!(err + .source() + .unwrap() + .to_string() + .starts_with("Unexpected stargate message")); +} + +#[test] +fn accepting_stargate() { + let mut app = AppBuilder::default() + .with_stargate(StargateAccepting) + .build(no_init); + + // store the contract + let creator_addr = app.api().addr_make("creator"); + let code = app.store_code_with_creator(creator_addr, stargate::contract()); + + // instantiate contract + let owner_addr = app.api().addr_make("owner"); + let contract_addr = app + .instantiate_contract(code, owner_addr, &Empty {}, &[], "tauri", None) + .unwrap(); + + // execute empty message on the contract, this contract returns stargate message + // which is just silently processed by accepting stargate keeper + let sender_addr = app.api().addr_make("sender"); + assert!(app + .execute_contract(sender_addr, contract_addr, &Empty {}, &[]) + .is_ok()); +} From 76ef259b3b7ffd67c50b02d1c196484f3ba70ec2 Mon Sep 17 00:00:00 2001 From: Dariusz Depta Date: Wed, 29 Nov 2023 12:11:19 +0100 Subject: [PATCH 5/9] Refactoring. --- src/test_helpers/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test_helpers/mod.rs b/src/test_helpers/mod.rs index dc87c895..16d23082 100644 --- a/src/test_helpers/mod.rs +++ b/src/test_helpers/mod.rs @@ -12,6 +12,7 @@ pub mod hackatom; pub mod ibc; pub mod payout; pub mod reflect; +pub mod stargate; /// Custom message for testing purposes. #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] From 2d4dd795c129df069e41edec2e888e763f8e2bfe Mon Sep 17 00:00:00 2001 From: Dariusz Depta Date: Wed, 29 Nov 2023 12:16:13 +0100 Subject: [PATCH 6/9] Refactored tests. --- src/tests/test_stargate.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/tests/test_stargate.rs b/src/tests/test_stargate.rs index 47464e04..92fcb69c 100644 --- a/src/tests/test_stargate.rs +++ b/src/tests/test_stargate.rs @@ -13,14 +13,13 @@ fn default_stargate() { // instantiate contract let owner_addr = app.api().addr_make("owner"); let contract_addr = app - .instantiate_contract(code, owner_addr, &Empty {}, &[], "tauri", None) + .instantiate_contract(code, owner_addr.clone(), &Empty {}, &[], "tauri", None) .unwrap(); // execute empty message on the contract, this contract returns stargate message // which is rejected by default failing stargate keeper - let sender_addr = app.api().addr_make("sender"); let err = app - .execute_contract(sender_addr, contract_addr, &Empty {}, &[]) + .execute_contract(owner_addr, contract_addr, &Empty {}, &[]) .unwrap_err(); // source error message comes from failing stargate keeper @@ -44,13 +43,12 @@ fn accepting_stargate() { // instantiate contract let owner_addr = app.api().addr_make("owner"); let contract_addr = app - .instantiate_contract(code, owner_addr, &Empty {}, &[], "tauri", None) + .instantiate_contract(code, owner_addr.clone(), &Empty {}, &[], "tauri", None) .unwrap(); // execute empty message on the contract, this contract returns stargate message // which is just silently processed by accepting stargate keeper - let sender_addr = app.api().addr_make("sender"); assert!(app - .execute_contract(sender_addr, contract_addr, &Empty {}, &[]) + .execute_contract(owner_addr, contract_addr, &Empty {}, &[]) .is_ok()); } From 01859745a789ae0a04e837a945419b39758ca295 Mon Sep 17 00:00:00 2001 From: Dariusz Depta Date: Wed, 29 Nov 2023 12:40:00 +0100 Subject: [PATCH 7/9] Updated documentation. --- src/stargate.rs | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/src/stargate.rs b/src/stargate.rs index 23b26f31..39d23aac 100644 --- a/src/stargate.rs +++ b/src/stargate.rs @@ -1,5 +1,3 @@ -//! add-docs - use crate::error::AnyResult; use crate::{AppResponse, CosmosRouter}; use anyhow::bail; @@ -9,8 +7,15 @@ use serde::de::DeserializeOwned; use std::fmt::Debug; /// Stargate interface. +/// +/// This trait provides the default behaviour for all functions +/// that is equal to [StargateFailing] implementation. pub trait Stargate { /// Processes stargate messages. + /// + /// The `CosmosMsg::Stargate` message is unwrapped before processing. + /// The `type_url` and `value` attributes of `CosmosMsg::Stargate` + /// are passed directly to this handler. fn execute( &self, api: &dyn Api, @@ -35,6 +40,10 @@ pub trait Stargate { } /// Processes stargate queries. + /// + /// The `QueryRequest::Stargate` query request is unwrapped before processing. + /// The `path` and `data` attributes of `QueryRequest::Stargate` are passed + /// directly to this handler. fn query( &self, api: &dyn Api, @@ -62,34 +71,36 @@ impl Stargate for StargateFailing {} pub struct StargateAccepting; impl Stargate for StargateAccepting { - /// Accepts all stargate messages. + /// Accepts all stargate messages. Returns default `AppResponse`. fn execute( &self, - _api: &dyn Api, - _storage: &mut dyn Storage, - _router: &dyn CosmosRouter, - _block: &BlockInfo, - _sender: Addr, - _type_url: String, - _value: Binary, + api: &dyn Api, + storage: &mut dyn Storage, + router: &dyn CosmosRouter, + block: &BlockInfo, + sender: Addr, + type_url: String, + value: Binary, ) -> AnyResult where ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static, QueryC: CustomQuery + DeserializeOwned + 'static, { + let _ = (api, storage, router, block, sender, type_url, value); Ok(AppResponse::default()) } - /// Accepts all stargate queries. + /// Accepts all stargate queries. Returns default `Binary`. fn query( &self, - _api: &dyn Api, - _storage: &dyn Storage, - _querier: &dyn Querier, - _block: &BlockInfo, - _path: String, - _data: Binary, + api: &dyn Api, + storage: &dyn Storage, + querier: &dyn Querier, + block: &BlockInfo, + path: String, + data: Binary, ) -> AnyResult { + let _ = (api, storage, querier, block, path, data); Ok(Binary::default()) } } From 93ebb12722e828924d674b73b951f1a770124d01 Mon Sep 17 00:00:00 2001 From: Dariusz Depta Date: Wed, 29 Nov 2023 12:46:32 +0100 Subject: [PATCH 8/9] Refactoring --- src/app_builder.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app_builder.rs b/src/app_builder.rs index 4b2f4b33..dd4c83e4 100644 --- a/src/app_builder.rs +++ b/src/app_builder.rs @@ -1,9 +1,9 @@ //! Implementation of the builder for [App]. -use crate::stargate::{Stargate, StargateFailing}; use crate::{ App, Bank, BankKeeper, Distribution, DistributionKeeper, FailingModule, Gov, GovFailingModule, - Ibc, IbcFailingModule, Module, Router, StakeKeeper, Staking, Wasm, WasmKeeper, + Ibc, IbcFailingModule, Module, Router, StakeKeeper, Staking, Stargate, StargateFailing, Wasm, + WasmKeeper, }; use cosmwasm_std::testing::{mock_env, MockApi, MockStorage}; use cosmwasm_std::{Api, BlockInfo, CustomQuery, Empty, Storage}; From 7754d8993fac78d464bd64f7f0ad58172b595526 Mon Sep 17 00:00:00 2001 From: Dariusz Depta Date: Wed, 29 Nov 2023 13:34:06 +0100 Subject: [PATCH 9/9] Refactoring. --- tests/test_app_builder/test_with_stargate.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/tests/test_app_builder/test_with_stargate.rs b/tests/test_app_builder/test_with_stargate.rs index fb668557..624e701f 100644 --- a/tests/test_app_builder/test_with_stargate.rs +++ b/tests/test_app_builder/test_with_stargate.rs @@ -5,7 +5,8 @@ use cosmwasm_std::{ }; use cw_multi_test::error::AnyResult; use cw_multi_test::{ - AppBuilder, AppResponse, CosmosRouter, Executor, Stargate, StargateAccepting, StargateFailing, + no_init, AppBuilder, AppResponse, CosmosRouter, Executor, Stargate, StargateAccepting, + StargateFailing, }; use schemars::JsonSchema; use serde::de::DeserializeOwned; @@ -60,9 +61,7 @@ fn building_app_with_custom_stargate_should_work() { // build the application with custom stargate keeper let app_builder = AppBuilder::default(); - let mut app = app_builder - .with_stargate(stargate_keeper) - .build(|_, _, _| {}); + let mut app = app_builder.with_stargate(stargate_keeper).build(no_init); // executing stargate message should return // an error defined in custom stargate keeper @@ -97,9 +96,7 @@ fn building_app_with_custom_stargate_should_work() { #[test] fn building_app_with_accepting_stargate_should_work() { let app_builder = AppBuilder::default(); - let mut app = app_builder - .with_stargate(StargateAccepting) - .build(|_, _, _| {}); + let mut app = app_builder.with_stargate(StargateAccepting).build(no_init); app.execute( Addr::unchecked("sender"), @@ -122,9 +119,7 @@ fn building_app_with_accepting_stargate_should_work() { #[test] fn building_app_with_failing_stargate_should_work() { let app_builder = AppBuilder::default(); - let mut app = app_builder - .with_stargate(StargateFailing) - .build(|_, _, _| {}); + let mut app = app_builder.with_stargate(StargateFailing).build(no_init); app.execute( Addr::unchecked("sender"),