From be022503246aa46c5a3211631a9650e6c1752105 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 14 Sep 2021 22:10:45 +0200 Subject: [PATCH 1/7] Pull out Router.execute into a trait --- packages/multi-test/src/app.rs | 35 ++++++++++++++++++++++++--------- packages/multi-test/src/wasm.rs | 2 +- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/packages/multi-test/src/app.rs b/packages/multi-test/src/app.rs index 93fb30ba2..7186ae6bf 100644 --- a/packages/multi-test/src/app.rs +++ b/packages/multi-test/src/app.rs @@ -492,21 +492,38 @@ impl Router { _ => unimplemented!(), } } +} + +pub trait CosmosExecutor { + type ExecC: Clone + fmt::Debug + PartialEq + JsonSchema; - pub fn execute( + fn execute( &self, api: &dyn Api, storage: &mut dyn Storage, block: &BlockInfo, sender: Addr, - msg: CosmosMsg, - ) -> AnyResult - where - CustomT::ExecC: std::fmt::Debug + Clone + PartialEq + JsonSchema, - WasmT: Wasm, - BankT: Bank, - CustomT: CustomHandler, - { + msg: CosmosMsg, + ) -> AnyResult; +} + +impl CosmosExecutor for Router +where + CustomT::ExecC: std::fmt::Debug + Clone + PartialEq + JsonSchema, + WasmT: Wasm, + BankT: Bank, + CustomT: CustomHandler, +{ + type ExecC = CustomT::ExecC; + + fn execute( + &self, + api: &dyn Api, + storage: &mut dyn Storage, + block: &BlockInfo, + sender: Addr, + msg: CosmosMsg, + ) -> AnyResult { match msg { CosmosMsg::Wasm(msg) => self.wasm.execute(api, storage, &self, block, sender, msg), CosmosMsg::Bank(msg) => self.bank.execute(storage, sender, msg), diff --git a/packages/multi-test/src/wasm.rs b/packages/multi-test/src/wasm.rs index a1c4f7cf3..addbc4ed4 100644 --- a/packages/multi-test/src/wasm.rs +++ b/packages/multi-test/src/wasm.rs @@ -15,7 +15,7 @@ use serde::{Deserialize, Serialize}; use cw_storage_plus::Map; -use crate::app::{Router, RouterQuerier}; +use crate::app::{CosmosExecutor, Router, RouterQuerier}; use crate::contracts::Contract; use crate::error::Error; use crate::executor::AppResponse; From 10c97f63e37cf3b02d04896e01d6b3296038194d Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Tue, 14 Sep 2021 22:14:24 +0200 Subject: [PATCH 2/7] Try to use trait object... fail --- packages/multi-test/src/wasm.rs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/multi-test/src/wasm.rs b/packages/multi-test/src/wasm.rs index addbc4ed4..ec28c548e 100644 --- a/packages/multi-test/src/wasm.rs +++ b/packages/multi-test/src/wasm.rs @@ -63,7 +63,7 @@ pub trait Wasm { &self, api: &dyn Api, storage: &mut dyn Storage, - router: &Router, + router: &dyn CosmosExecutor, block: &BlockInfo, sender: Addr, msg: WasmMsg, @@ -85,7 +85,7 @@ pub trait Wasm { api: &dyn Api, contract_addr: Addr, storage: &mut dyn Storage, - router: &Router, + router: &dyn CosmosExecutor, block: &BlockInfo, msg: Vec, ) -> AnyResult @@ -142,7 +142,7 @@ where &self, api: &dyn Api, storage: &mut dyn Storage, - router: &Router, + router: &dyn CosmosExecutor, block: &BlockInfo, sender: Addr, msg: WasmMsg, @@ -173,7 +173,7 @@ where api: &dyn Api, contract: Addr, storage: &mut dyn Storage, - router: &Router, + router: &dyn CosmosExecutor, block: &BlockInfo, msg: Vec, ) -> AnyResult @@ -227,7 +227,7 @@ where &self, api: &dyn Api, storage: &mut dyn Storage, - router: &Router, + router: &dyn CosmosExecutor, block: &BlockInfo, sender: T, recipient: String, @@ -255,7 +255,7 @@ where &self, api: &dyn Api, storage: &mut dyn Storage, - router: &Router, + router: &dyn CosmosExecutor, block: &BlockInfo, sender: Addr, wasm_msg: WasmMsg, @@ -397,7 +397,7 @@ where fn execute_submsg( &self, api: &dyn Api, - router: &Router, + router: &dyn CosmosExecutor, storage: &mut dyn Storage, block: &BlockInfo, contract: Addr, @@ -456,7 +456,7 @@ where fn _reply( &self, api: &dyn Api, - router: &Router, + router: &dyn CosmosExecutor, storage: &mut dyn Storage, block: &BlockInfo, contract: Addr, @@ -529,7 +529,7 @@ where fn process_response( &self, api: &dyn Api, - router: &Router, + router: &dyn CosmosExecutor, storage: &mut dyn Storage, block: &BlockInfo, contract: Addr, @@ -587,7 +587,7 @@ where api: &dyn Api, storage: &mut dyn Storage, address: Addr, - router: &Router, + router: &dyn CosmosExecutor, block: &BlockInfo, info: MessageInfo, msg: Vec, @@ -611,7 +611,7 @@ where address: Addr, api: &dyn Api, storage: &mut dyn Storage, - router: &Router, + router: &dyn CosmosExecutor, block: &BlockInfo, info: MessageInfo, msg: Vec, @@ -635,7 +635,7 @@ where address: Addr, api: &dyn Api, storage: &mut dyn Storage, - router: &Router, + router: &dyn CosmosExecutor, block: &BlockInfo, reply: Reply, ) -> AnyResult> @@ -658,7 +658,7 @@ where address: Addr, api: &dyn Api, storage: &mut dyn Storage, - router: &Router, + router: &dyn CosmosExecutor, block: &BlockInfo, msg: Vec, ) -> AnyResult> @@ -681,7 +681,7 @@ where address: Addr, api: &dyn Api, storage: &mut dyn Storage, - router: &Router, + router: &dyn CosmosExecutor, block: &BlockInfo, msg: Vec, ) -> AnyResult> @@ -740,7 +740,7 @@ where &self, api: &dyn Api, storage: &mut dyn Storage, - router: &Router, + router: &dyn CosmosExecutor, block: &BlockInfo, address: Addr, action: F, From 95e47c4c3ea09e840a09ef5b1c87000c76aecfea Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 15 Sep 2021 11:46:23 +0200 Subject: [PATCH 3/7] Fix most compile errors, by removing trait limitations on CosmosMsg --- packages/multi-test/src/app.rs | 58 ++++++++++++--- packages/multi-test/src/wasm.rs | 122 +++++++++----------------------- 2 files changed, 82 insertions(+), 98 deletions(-) diff --git a/packages/multi-test/src/app.rs b/packages/multi-test/src/app.rs index 7186ae6bf..98f400c70 100644 --- a/packages/multi-test/src/app.rs +++ b/packages/multi-test/src/app.rs @@ -2,13 +2,13 @@ use std::fmt::{self, Debug}; use cosmwasm_std::testing::{mock_env, MockApi, MockStorage}; use cosmwasm_std::{ - from_slice, to_vec, Addr, Api, Binary, BlockInfo, Coin, ContractResult, CosmosMsg, CustomQuery, + from_slice, to_vec, Addr, Api, BankMsg, Binary, BlockInfo, Coin, ContractResult, CustomQuery, Empty, Querier, QuerierResult, QuerierWrapper, QueryRequest, Storage, SystemError, - SystemResult, + SystemResult, WasmMsg, }; use schemars::JsonSchema; use serde::de::DeserializeOwned; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use crate::bank::Bank; use crate::contracts::Contract; @@ -101,7 +101,11 @@ where StorageT: Storage, CustomT: CustomHandler, { - fn execute(&mut self, sender: Addr, msg: CosmosMsg) -> AnyResult { + fn execute( + &mut self, + sender: Addr, + msg: cosmwasm_std::CosmosMsg, + ) -> AnyResult { let mut all = self.execute_multi(sender, vec![msg])?; let res = all.pop().unwrap(); Ok(res) @@ -385,7 +389,7 @@ where pub fn execute_multi( &mut self, sender: Addr, - msgs: Vec>, + msgs: Vec>, ) -> AnyResult> { // we need to do some caching of storage here, once in the entry point: // meaning, wrap current state, all writes go to a cache, only when execute @@ -400,7 +404,7 @@ where transactional(&mut *storage, |write_cache, _| { msgs.into_iter() - .map(|msg| router.execute(&*api, write_cache, block, sender.clone(), msg)) + .map(|msg| router.execute(&*api, write_cache, block, sender.clone(), msg.into())) .collect() }) } @@ -495,7 +499,7 @@ impl Router { } pub trait CosmosExecutor { - type ExecC: Clone + fmt::Debug + PartialEq + JsonSchema; + type ExecC; fn execute( &self, @@ -507,6 +511,44 @@ pub trait CosmosExecutor { ) -> AnyResult; } +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +// See https://github.com/serde-rs/serde/issues/1296 why we cannot add De-Serialize trait bounds to T +pub enum CosmosMsg { + Bank(BankMsg), + // by default we use RawMsg, but a contract can override that + // to call into more app-specific code (whatever they define) + Custom(T), + Wasm(WasmMsg), +} + +impl Into> for CosmosMsg +where + T: Clone + fmt::Debug + PartialEq + JsonSchema, +{ + fn into(self) -> cosmwasm_std::CosmosMsg { + match self { + CosmosMsg::Bank(b) => cosmwasm_std::CosmosMsg::Bank(b), + CosmosMsg::Custom(c) => cosmwasm_std::CosmosMsg::Custom(c), + CosmosMsg::Wasm(w) => cosmwasm_std::CosmosMsg::Wasm(w), + } + } +} + +impl From> for CosmosMsg +where + T: Clone + fmt::Debug + PartialEq + JsonSchema, +{ + fn from(input: cosmwasm_std::CosmosMsg) -> CosmosMsg { + match input { + cosmwasm_std::CosmosMsg::Bank(b) => CosmosMsg::Bank(b), + cosmwasm_std::CosmosMsg::Custom(c) => CosmosMsg::Custom(c), + cosmwasm_std::CosmosMsg::Wasm(w) => CosmosMsg::Wasm(w), + _ => panic!("Unsupported type"), + } + } +} + impl CosmosExecutor for Router where CustomT::ExecC: std::fmt::Debug + Clone + PartialEq + JsonSchema, @@ -525,7 +567,7 @@ where msg: CosmosMsg, ) -> AnyResult { match msg { - CosmosMsg::Wasm(msg) => self.wasm.execute(api, storage, &self, block, sender, msg), + CosmosMsg::Wasm(msg) => self.wasm.execute(api, storage, self, block, sender, msg), CosmosMsg::Bank(msg) => self.bank.execute(storage, sender, msg), CosmosMsg::Custom(msg) => self.custom.execute(api, storage, block, sender, msg), _ => unimplemented!(), diff --git a/packages/multi-test/src/wasm.rs b/packages/multi-test/src/wasm.rs index ec28c548e..256048588 100644 --- a/packages/multi-test/src/wasm.rs +++ b/packages/multi-test/src/wasm.rs @@ -15,12 +15,11 @@ use serde::{Deserialize, Serialize}; use cw_storage_plus::Map; -use crate::app::{CosmosExecutor, Router, RouterQuerier}; +use crate::app::{CosmosExecutor, RouterQuerier}; use crate::contracts::Contract; use crate::error::Error; use crate::executor::AppResponse; use crate::transactions::transactional; -use crate::{Bank, CustomHandler}; use cosmwasm_std::testing::mock_wasmd_attr; use anyhow::{anyhow, bail, Result as AnyResult}; @@ -59,7 +58,7 @@ pub trait Wasm { ) -> AnyResult; /// Handles all WasmMsg messages - fn execute( + fn execute( &self, api: &dyn Api, storage: &mut dyn Storage, @@ -67,11 +66,7 @@ pub trait Wasm { block: &BlockInfo, sender: Addr, msg: WasmMsg, - ) -> AnyResult - where - Self: Sized, - BankT: Bank, - CustomT: CustomHandler; + ) -> AnyResult; // Add a new contract. Must be done on the base object, when no contracts running fn store_code(&mut self, code: Box>) -> usize; @@ -80,7 +75,7 @@ pub trait Wasm { fn contract_data(&self, storage: &dyn Storage, address: &Addr) -> AnyResult; /// Admin interface, cannot be called via CosmosMsg - fn sudo( + fn sudo( &self, api: &dyn Api, contract_addr: Addr, @@ -88,11 +83,7 @@ pub trait Wasm { router: &dyn CosmosExecutor, block: &BlockInfo, msg: Vec, - ) -> AnyResult - where - Self: Sized, - BankT: Bank, - CustomT: CustomHandler; + ) -> AnyResult; } pub struct WasmKeeper { @@ -138,7 +129,7 @@ where } } - fn execute( + fn execute( &self, api: &dyn Api, storage: &mut dyn Storage, @@ -146,11 +137,7 @@ where block: &BlockInfo, sender: Addr, msg: WasmMsg, - ) -> AnyResult - where - BankT: Bank, - CustomT: CustomHandler, - { + ) -> AnyResult { let (resender, res, custom_event) = self.execute_wasm(api, storage, router, block, sender, msg)?; @@ -168,7 +155,7 @@ where self.load_contract(storage, address) } - fn sudo( + fn sudo( &self, api: &dyn Api, contract: Addr, @@ -176,11 +163,7 @@ where router: &dyn CosmosExecutor, block: &BlockInfo, msg: Vec, - ) -> AnyResult - where - BankT: Bank, - CustomT: CustomHandler, - { + ) -> AnyResult { let custom_event = Event::new("sudo").add_attribute(CONTRACT_ATTR, &contract); let res = self.call_sudo(contract.clone(), api, storage, router, block, msg)?; @@ -223,7 +206,7 @@ where data.into() } - fn send( + fn send( &self, api: &dyn Api, storage: &mut dyn Storage, @@ -235,14 +218,12 @@ where ) -> AnyResult where T: Into, - BankT: Bank, - CustomT: CustomHandler, { if !amount.is_empty() { - let msg = BankMsg::Send { + let msg: cosmwasm_std::CosmosMsg = BankMsg::Send { to_address: recipient, amount: amount.to_vec(), - }; + }.into(); let res = router.execute(api, storage, block, sender.into(), msg.into())?; Ok(res) } else { @@ -251,7 +232,7 @@ where } // this returns the contract address as well, so we can properly resend the data - fn execute_wasm( + fn execute_wasm( &self, api: &dyn Api, storage: &mut dyn Storage, @@ -259,11 +240,7 @@ where block: &BlockInfo, sender: Addr, wasm_msg: WasmMsg, - ) -> AnyResult<(Addr, Response, Event)> - where - BankT: Bank, - CustomT: CustomHandler, - { + ) -> AnyResult<(Addr, Response, Event)> { match wasm_msg { WasmMsg::Execute { contract_addr, @@ -394,7 +371,7 @@ where /// /// The `data` on `AppResponse` is data returned from `reply` call, not from execution of /// submessage itself. In case if `reply` is not called, no `data` is set. - fn execute_submsg( + fn execute_submsg( &self, api: &dyn Api, router: &dyn CosmosExecutor, @@ -402,18 +379,14 @@ where block: &BlockInfo, contract: Addr, msg: SubMsg, - ) -> AnyResult - where - BankT: Bank, - CustomT: CustomHandler, - { + ) -> AnyResult { let SubMsg { msg, id, reply_on, .. } = msg; // execute in cache let res = transactional(storage, |write_cache, _| { - router.execute(api, write_cache, block, contract.clone(), msg) + router.execute(api, write_cache, block, contract.clone(), msg.into()) }); // call reply if meaningful @@ -453,7 +426,7 @@ where } } - fn _reply( + fn _reply( &self, api: &dyn Api, router: &dyn CosmosExecutor, @@ -461,11 +434,7 @@ where block: &BlockInfo, contract: Addr, reply: Reply, - ) -> AnyResult - where - BankT: Bank, - CustomT: CustomHandler, - { + ) -> AnyResult { let ok_attr = if reply.result.is_ok() { "handle_success" } else { @@ -526,7 +495,7 @@ where (app, messages) } - fn process_response( + fn process_response( &self, api: &dyn Api, router: &dyn CosmosExecutor, @@ -535,11 +504,7 @@ where contract: Addr, response: AppResponse, messages: Vec>, - ) -> AnyResult - where - BankT: Bank, - CustomT: CustomHandler, - { + ) -> AnyResult { let AppResponse { mut events, data } = response; // recurse in all messages @@ -582,7 +547,7 @@ where Ok(addr) } - pub fn call_execute( + pub fn call_execute( &self, api: &dyn Api, storage: &mut dyn Storage, @@ -591,11 +556,7 @@ where block: &BlockInfo, info: MessageInfo, msg: Vec, - ) -> AnyResult> - where - BankT: Bank, - CustomT: CustomHandler, - { + ) -> AnyResult> { Self::verify_response(self.with_storage( api, storage, @@ -606,7 +567,7 @@ where )?) } - pub fn call_instantiate( + pub fn call_instantiate( &self, address: Addr, api: &dyn Api, @@ -615,11 +576,7 @@ where block: &BlockInfo, info: MessageInfo, msg: Vec, - ) -> AnyResult> - where - BankT: Bank, - CustomT: CustomHandler, - { + ) -> AnyResult> { Self::verify_response(self.with_storage( api, storage, @@ -630,7 +587,7 @@ where )?) } - pub fn call_reply( + pub fn call_reply( &self, address: Addr, api: &dyn Api, @@ -638,11 +595,7 @@ where router: &dyn CosmosExecutor, block: &BlockInfo, reply: Reply, - ) -> AnyResult> - where - BankT: Bank, - CustomT: CustomHandler, - { + ) -> AnyResult> { Self::verify_response(self.with_storage( api, storage, @@ -653,7 +606,7 @@ where )?) } - pub fn call_sudo( + pub fn call_sudo( &self, address: Addr, api: &dyn Api, @@ -661,11 +614,7 @@ where router: &dyn CosmosExecutor, block: &BlockInfo, msg: Vec, - ) -> AnyResult> - where - BankT: Bank, - CustomT: CustomHandler, - { + ) -> AnyResult> { Self::verify_response(self.with_storage( api, storage, @@ -676,7 +625,7 @@ where )?) } - pub fn call_migrate( + pub fn call_migrate( &self, address: Addr, api: &dyn Api, @@ -684,11 +633,7 @@ where router: &dyn CosmosExecutor, block: &BlockInfo, msg: Vec, - ) -> AnyResult> - where - BankT: Bank, - CustomT: CustomHandler, - { + ) -> AnyResult> { Self::verify_response(self.with_storage( api, storage, @@ -736,7 +681,7 @@ where action(handler, deps, env) } - fn with_storage( + fn with_storage( &self, api: &dyn Api, storage: &mut dyn Storage, @@ -747,10 +692,7 @@ where ) -> AnyResult where F: FnOnce(&Box>, DepsMut, Env) -> AnyResult, - BankT: Bank, - CustomT: CustomHandler, ExecC: DeserializeOwned, - QueryC: 'static, { let contract = self.load_contract(storage, &address)?; let handler = self From af20062ff1bcaf7bf38ea14cf69e3e1f8a864486 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 15 Sep 2021 12:04:50 +0200 Subject: [PATCH 4/7] cargo build works --- packages/multi-test/src/app.rs | 122 +++++++++++++++++--------------- packages/multi-test/src/wasm.rs | 35 ++++----- 2 files changed, 82 insertions(+), 75 deletions(-) diff --git a/packages/multi-test/src/app.rs b/packages/multi-test/src/app.rs index 98f400c70..d4ae8ecb8 100644 --- a/packages/multi-test/src/app.rs +++ b/packages/multi-test/src/app.rs @@ -453,13 +453,20 @@ pub struct Router { pub(crate) custom: Custom, } -impl Router { +impl Router +where + CustomT::ExecC: Clone + fmt::Debug + PartialEq + JsonSchema + DeserializeOwned + 'static, + CustomT::QueryC: CustomQuery + DeserializeOwned + 'static, + CustomT: CustomHandler, + WasmT: Wasm, + BankT: Bank, +{ pub fn querier<'a>( &'a self, api: &'a dyn Api, storage: &'a dyn Storage, block_info: &'a BlockInfo, - ) -> RouterQuerier<'a, BankT, CustomT, WasmT> { + ) -> RouterQuerier<'a, CustomT::ExecC, CustomT::QueryC> { RouterQuerier { router: self, api, @@ -467,48 +474,6 @@ impl Router { block_info, } } - - /// this is used by `RouterQuerier` to actual implement the `Querier` interface. - /// you most likely want to use `router.querier(storage, block).wrap()` to get a - /// QuerierWrapper to interact with - pub fn query( - &self, - api: &dyn Api, - storage: &dyn Storage, - block: &BlockInfo, - request: QueryRequest, - ) -> AnyResult - where - CustomT::QueryC: CustomQuery + DeserializeOwned + 'static, - CustomT::ExecC: - std::fmt::Debug + PartialEq + Clone + JsonSchema + DeserializeOwned + 'static, - WasmT: Wasm, - BankT: Bank, - CustomT: CustomHandler, - { - match request { - QueryRequest::Wasm(req) => { - self.wasm - .query(api, storage, &self.querier(api, storage, block), block, req) - } - QueryRequest::Bank(req) => self.bank.query(api, storage, req), - QueryRequest::Custom(req) => self.custom.query(api, storage, block, req), - _ => unimplemented!(), - } - } -} - -pub trait CosmosExecutor { - type ExecC; - - fn execute( - &self, - api: &dyn Api, - storage: &mut dyn Storage, - block: &BlockInfo, - sender: Addr, - msg: CosmosMsg, - ) -> AnyResult; } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] @@ -549,14 +514,38 @@ where } } -impl CosmosExecutor for Router +pub trait CosmosRouter { + type ExecC; + type QueryC: CustomQuery; + + fn execute( + &self, + api: &dyn Api, + storage: &mut dyn Storage, + block: &BlockInfo, + sender: Addr, + msg: CosmosMsg, + ) -> AnyResult; + + fn query( + &self, + api: &dyn Api, + storage: &dyn Storage, + block: &BlockInfo, + request: QueryRequest, + ) -> AnyResult; +} + +impl CosmosRouter for Router where - CustomT::ExecC: std::fmt::Debug + Clone + PartialEq + JsonSchema, + CustomT::ExecC: std::fmt::Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static, + CustomT::QueryC: CustomQuery + DeserializeOwned + 'static, + CustomT: CustomHandler, WasmT: Wasm, BankT: Bank, - CustomT: CustomHandler, { type ExecC = CustomT::ExecC; + type QueryC = CustomT::QueryC; fn execute( &self, @@ -570,21 +559,41 @@ where CosmosMsg::Wasm(msg) => self.wasm.execute(api, storage, self, block, sender, msg), CosmosMsg::Bank(msg) => self.bank.execute(storage, sender, msg), CosmosMsg::Custom(msg) => self.custom.execute(api, storage, block, sender, msg), + } + } + + /// this is used by `RouterQuerier` to actual implement the `Querier` interface. + /// you most likely want to use `router.querier(storage, block).wrap()` to get a + /// QuerierWrapper to interact with + fn query( + &self, + api: &dyn Api, + storage: &dyn Storage, + block: &BlockInfo, + request: QueryRequest, + ) -> AnyResult { + match request { + QueryRequest::Wasm(req) => { + self.wasm + .query(api, storage, &self.querier(api, storage, block), block, req) + } + QueryRequest::Bank(req) => self.bank.query(api, storage, req), + QueryRequest::Custom(req) => self.custom.query(api, storage, block, req), _ => unimplemented!(), } } } -pub struct RouterQuerier<'a, Bank, Custom, Wasm> { - router: &'a Router, +pub struct RouterQuerier<'a, ExecC, QueryC> { + router: &'a dyn CosmosRouter, api: &'a dyn Api, storage: &'a dyn Storage, block_info: &'a BlockInfo, } -impl<'a, Bank, Custom, Wasm> RouterQuerier<'a, Bank, Custom, Wasm> { +impl<'a, ExecC, QueryC> RouterQuerier<'a, ExecC, QueryC> { pub fn new( - router: &'a Router, + router: &'a dyn CosmosRouter, api: &'a dyn Api, storage: &'a dyn Storage, block_info: &'a BlockInfo, @@ -598,16 +607,13 @@ impl<'a, Bank, Custom, Wasm> RouterQuerier<'a, Bank, Custom, Wasm> { } } -impl<'a, BankT, CustomT, WasmT> Querier for RouterQuerier<'a, BankT, CustomT, WasmT> +impl<'a, ExecC, QueryC> Querier for RouterQuerier<'a, ExecC, QueryC> where - CustomT::ExecC: Clone + fmt::Debug + PartialEq + JsonSchema + DeserializeOwned + 'static, - CustomT::QueryC: CustomQuery + DeserializeOwned + 'static, - WasmT: Wasm, - BankT: Bank, - CustomT: CustomHandler, + ExecC: Clone + fmt::Debug + PartialEq + JsonSchema + DeserializeOwned + 'static, + QueryC: CustomQuery + DeserializeOwned + 'static, { fn raw_query(&self, bin_request: &[u8]) -> QuerierResult { - let request: QueryRequest = match from_slice(bin_request) { + let request: QueryRequest = match from_slice(bin_request) { Ok(v) => v, Err(e) => { return SystemResult::Err(SystemError::InvalidRequest { diff --git a/packages/multi-test/src/wasm.rs b/packages/multi-test/src/wasm.rs index 256048588..f5bee0dea 100644 --- a/packages/multi-test/src/wasm.rs +++ b/packages/multi-test/src/wasm.rs @@ -15,7 +15,7 @@ use serde::{Deserialize, Serialize}; use cw_storage_plus::Map; -use crate::app::{CosmosExecutor, RouterQuerier}; +use crate::app::{CosmosRouter, RouterQuerier}; use crate::contracts::Contract; use crate::error::Error; use crate::executor::AppResponse; @@ -62,7 +62,7 @@ pub trait Wasm { &self, api: &dyn Api, storage: &mut dyn Storage, - router: &dyn CosmosExecutor, + router: &dyn CosmosRouter, block: &BlockInfo, sender: Addr, msg: WasmMsg, @@ -80,7 +80,7 @@ pub trait Wasm { api: &dyn Api, contract_addr: Addr, storage: &mut dyn Storage, - router: &dyn CosmosExecutor, + router: &dyn CosmosRouter, block: &BlockInfo, msg: Vec, ) -> AnyResult; @@ -133,7 +133,7 @@ where &self, api: &dyn Api, storage: &mut dyn Storage, - router: &dyn CosmosExecutor, + router: &dyn CosmosRouter, block: &BlockInfo, sender: Addr, msg: WasmMsg, @@ -160,7 +160,7 @@ where api: &dyn Api, contract: Addr, storage: &mut dyn Storage, - router: &dyn CosmosExecutor, + router: &dyn CosmosRouter, block: &BlockInfo, msg: Vec, ) -> AnyResult { @@ -210,7 +210,7 @@ where &self, api: &dyn Api, storage: &mut dyn Storage, - router: &dyn CosmosExecutor, + router: &dyn CosmosRouter, block: &BlockInfo, sender: T, recipient: String, @@ -223,7 +223,8 @@ where let msg: cosmwasm_std::CosmosMsg = BankMsg::Send { to_address: recipient, amount: amount.to_vec(), - }.into(); + } + .into(); let res = router.execute(api, storage, block, sender.into(), msg.into())?; Ok(res) } else { @@ -236,7 +237,7 @@ where &self, api: &dyn Api, storage: &mut dyn Storage, - router: &dyn CosmosExecutor, + router: &dyn CosmosRouter, block: &BlockInfo, sender: Addr, wasm_msg: WasmMsg, @@ -374,7 +375,7 @@ where fn execute_submsg( &self, api: &dyn Api, - router: &dyn CosmosExecutor, + router: &dyn CosmosRouter, storage: &mut dyn Storage, block: &BlockInfo, contract: Addr, @@ -429,7 +430,7 @@ where fn _reply( &self, api: &dyn Api, - router: &dyn CosmosExecutor, + router: &dyn CosmosRouter, storage: &mut dyn Storage, block: &BlockInfo, contract: Addr, @@ -498,7 +499,7 @@ where fn process_response( &self, api: &dyn Api, - router: &dyn CosmosExecutor, + router: &dyn CosmosRouter, storage: &mut dyn Storage, block: &BlockInfo, contract: Addr, @@ -552,7 +553,7 @@ where api: &dyn Api, storage: &mut dyn Storage, address: Addr, - router: &dyn CosmosExecutor, + router: &dyn CosmosRouter, block: &BlockInfo, info: MessageInfo, msg: Vec, @@ -572,7 +573,7 @@ where address: Addr, api: &dyn Api, storage: &mut dyn Storage, - router: &dyn CosmosExecutor, + router: &dyn CosmosRouter, block: &BlockInfo, info: MessageInfo, msg: Vec, @@ -592,7 +593,7 @@ where address: Addr, api: &dyn Api, storage: &mut dyn Storage, - router: &dyn CosmosExecutor, + router: &dyn CosmosRouter, block: &BlockInfo, reply: Reply, ) -> AnyResult> { @@ -611,7 +612,7 @@ where address: Addr, api: &dyn Api, storage: &mut dyn Storage, - router: &dyn CosmosExecutor, + router: &dyn CosmosRouter, block: &BlockInfo, msg: Vec, ) -> AnyResult> { @@ -630,7 +631,7 @@ where address: Addr, api: &dyn Api, storage: &mut dyn Storage, - router: &dyn CosmosExecutor, + router: &dyn CosmosRouter, block: &BlockInfo, msg: Vec, ) -> AnyResult> { @@ -685,7 +686,7 @@ where &self, api: &dyn Api, storage: &mut dyn Storage, - router: &dyn CosmosExecutor, + router: &dyn CosmosRouter, block: &BlockInfo, address: Addr, action: F, From 32f1cdf27c70d07a5e47ebd568fdcb6edd0c1541 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 15 Sep 2021 12:09:28 +0200 Subject: [PATCH 5/7] Fix tests --- packages/multi-test/src/app.rs | 22 +++++++++++----------- packages/multi-test/src/wasm.rs | 1 + 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/packages/multi-test/src/app.rs b/packages/multi-test/src/app.rs index d4ae8ecb8..90d683642 100644 --- a/packages/multi-test/src/app.rs +++ b/packages/multi-test/src/app.rs @@ -487,12 +487,12 @@ pub enum CosmosMsg { Wasm(WasmMsg), } -impl Into> for CosmosMsg +impl From> for cosmwasm_std::CosmosMsg where T: Clone + fmt::Debug + PartialEq + JsonSchema, { - fn into(self) -> cosmwasm_std::CosmosMsg { - match self { + fn from(input: CosmosMsg) -> Self { + match input { CosmosMsg::Bank(b) => cosmwasm_std::CosmosMsg::Bank(b), CosmosMsg::Custom(c) => cosmwasm_std::CosmosMsg::Custom(c), CosmosMsg::Wasm(w) => cosmwasm_std::CosmosMsg::Wasm(w), @@ -687,7 +687,7 @@ mod test { // send both tokens let to_send = vec![coin(30, "eth"), coin(5, "btc")]; - let msg: CosmosMsg = BankMsg::Send { + let msg: cosmwasm_std::CosmosMsg = BankMsg::Send { to_address: rcpt.clone().into(), amount: to_send, } @@ -702,7 +702,7 @@ mod test { app.execute(rcpt.clone(), msg).unwrap(); // cannot send too much - let msg = BankMsg::Send { + let msg: cosmwasm_std::CosmosMsg = BankMsg::Send { to_address: rcpt.into(), amount: coins(20, "btc"), } @@ -1154,12 +1154,12 @@ mod test { // cache 1 - send some tokens let mut cache = StorageTransaction::new(&app.storage); - let msg = BankMsg::Send { + let msg = CosmosMsg::Bank(BankMsg::Send { to_address: rcpt.clone().into(), amount: coins(25, "eth"), - }; + }); app.router - .execute(&app.api, &mut cache, &app.block, owner.clone(), msg.into()) + .execute(&app.api, &mut cache, &app.block, owner.clone(), msg) .unwrap(); // shows up in cache @@ -1170,12 +1170,12 @@ mod test { // now, second level cache transactional(&mut cache, |cache2, read| { - let msg = BankMsg::Send { + let msg = CosmosMsg::Bank(BankMsg::Send { to_address: rcpt.clone().into(), amount: coins(12, "eth"), - }; + }); app.router - .execute(&app.api, cache2, &app.block, owner, msg.into()) + .execute(&app.api, cache2, &app.block, owner, msg) .unwrap(); // shows up in 2nd cache diff --git a/packages/multi-test/src/wasm.rs b/packages/multi-test/src/wasm.rs index f5bee0dea..7219e9357 100644 --- a/packages/multi-test/src/wasm.rs +++ b/packages/multi-test/src/wasm.rs @@ -860,6 +860,7 @@ mod test { use cosmwasm_std::testing::{mock_env, mock_info, MockApi, MockQuerier, MockStorage}; use cosmwasm_std::{coin, from_slice, to_vec, BankMsg, Coin, CosmosMsg, Empty, StdError}; + use crate::app::Router; use crate::test_helpers::contracts::{error, payout}; use crate::transactions::StorageTransaction; use crate::BankKeeper; From f1b07568d0ded943bb171fadff80ace56e0fb16d Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 15 Sep 2021 16:04:48 +0200 Subject: [PATCH 6/7] Pull out custom CosmosMsg and make it cleaner --- packages/multi-test/Cargo.toml | 3 +- packages/multi-test/src/app.rs | 47 ++----------- packages/multi-test/src/lib.rs | 1 + packages/multi-test/src/untyped_msg.rs | 95 ++++++++++++++++++++++++++ 4 files changed, 103 insertions(+), 43 deletions(-) create mode 100644 packages/multi-test/src/untyped_msg.rs diff --git a/packages/multi-test/Cargo.toml b/packages/multi-test/Cargo.toml index 4735c49e0..812173f24 100644 --- a/packages/multi-test/Cargo.toml +++ b/packages/multi-test/Cargo.toml @@ -11,9 +11,10 @@ documentation = "https://docs.cosmwasm.com" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] -default = ["iterator"] +default = ["iterator", "staking"] iterator = ["cosmwasm-std/iterator"] stargate = ["cosmwasm-std/stargate"] +staking = ["cosmwasm-std/staking"] backtrace = ["anyhow/backtrace"] [dependencies] diff --git a/packages/multi-test/src/app.rs b/packages/multi-test/src/app.rs index 90d683642..fdb78ab39 100644 --- a/packages/multi-test/src/app.rs +++ b/packages/multi-test/src/app.rs @@ -2,19 +2,19 @@ use std::fmt::{self, Debug}; use cosmwasm_std::testing::{mock_env, MockApi, MockStorage}; use cosmwasm_std::{ - from_slice, to_vec, Addr, Api, BankMsg, Binary, BlockInfo, Coin, ContractResult, CustomQuery, - Empty, Querier, QuerierResult, QuerierWrapper, QueryRequest, Storage, SystemError, - SystemResult, WasmMsg, + from_slice, to_vec, Addr, Api, Binary, BlockInfo, Coin, ContractResult, CustomQuery, Empty, + Querier, QuerierResult, QuerierWrapper, QueryRequest, Storage, SystemError, SystemResult, }; use schemars::JsonSchema; use serde::de::DeserializeOwned; -use serde::{Deserialize, Serialize}; +use serde::Serialize; use crate::bank::Bank; use crate::contracts::Contract; use crate::custom_handler::{CustomHandler, PanickingCustomHandler}; use crate::executor::{AppResponse, Executor}; use crate::transactions::transactional; +use crate::untyped_msg::CosmosMsg; use crate::wasm::{ContractData, Wasm, WasmKeeper}; use crate::BankKeeper; @@ -476,44 +476,6 @@ where } } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -// See https://github.com/serde-rs/serde/issues/1296 why we cannot add De-Serialize trait bounds to T -pub enum CosmosMsg { - Bank(BankMsg), - // by default we use RawMsg, but a contract can override that - // to call into more app-specific code (whatever they define) - Custom(T), - Wasm(WasmMsg), -} - -impl From> for cosmwasm_std::CosmosMsg -where - T: Clone + fmt::Debug + PartialEq + JsonSchema, -{ - fn from(input: CosmosMsg) -> Self { - match input { - CosmosMsg::Bank(b) => cosmwasm_std::CosmosMsg::Bank(b), - CosmosMsg::Custom(c) => cosmwasm_std::CosmosMsg::Custom(c), - CosmosMsg::Wasm(w) => cosmwasm_std::CosmosMsg::Wasm(w), - } - } -} - -impl From> for CosmosMsg -where - T: Clone + fmt::Debug + PartialEq + JsonSchema, -{ - fn from(input: cosmwasm_std::CosmosMsg) -> CosmosMsg { - match input { - cosmwasm_std::CosmosMsg::Bank(b) => CosmosMsg::Bank(b), - cosmwasm_std::CosmosMsg::Custom(c) => CosmosMsg::Custom(c), - cosmwasm_std::CosmosMsg::Wasm(w) => CosmosMsg::Wasm(w), - _ => panic!("Unsupported type"), - } - } -} - pub trait CosmosRouter { type ExecC; type QueryC: CustomQuery; @@ -559,6 +521,7 @@ where CosmosMsg::Wasm(msg) => self.wasm.execute(api, storage, self, block, sender, msg), CosmosMsg::Bank(msg) => self.bank.execute(storage, sender, msg), CosmosMsg::Custom(msg) => self.custom.execute(api, storage, block, sender, msg), + _ => unimplemented!(), } } diff --git a/packages/multi-test/src/lib.rs b/packages/multi-test/src/lib.rs index 1c1e0fec4..c04ae504d 100644 --- a/packages/multi-test/src/lib.rs +++ b/packages/multi-test/src/lib.rs @@ -14,6 +14,7 @@ pub mod error; mod executor; mod test_helpers; mod transactions; +mod untyped_msg; mod wasm; pub use crate::app::{custom_app, next_block, App, AppBuilder, BasicApp, Router}; diff --git a/packages/multi-test/src/untyped_msg.rs b/packages/multi-test/src/untyped_msg.rs new file mode 100644 index 000000000..9e857fdcb --- /dev/null +++ b/packages/multi-test/src/untyped_msg.rs @@ -0,0 +1,95 @@ +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use std::fmt; + +use cosmwasm_std::{BankMsg, DistributionMsg, Empty, StakingMsg, WasmMsg}; + +/// This is needed so we can embed CosmosMsg as a trait bound. +/// See https://github.com/CosmWasm/cosmwasm/pull/1098 for a proper solution +/// (when we can deprecate this one) +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum CosmosMsg { + Bank(BankMsg), + // by default we use RawMsg, but a contract can override that + // to call into more app-specific code (whatever they define) + Custom(T), + #[cfg(feature = "staking")] + Distribution(DistributionMsg), + #[cfg(feature = "staking")] + Staking(StakingMsg), + Wasm(WasmMsg), +} + +impl From> for cosmwasm_std::CosmosMsg +where + T: Clone + fmt::Debug + PartialEq + JsonSchema, +{ + fn from(input: CosmosMsg) -> Self { + match input { + CosmosMsg::Bank(b) => cosmwasm_std::CosmosMsg::Bank(b), + CosmosMsg::Custom(c) => cosmwasm_std::CosmosMsg::Custom(c), + #[cfg(feature = "staking")] + CosmosMsg::Distribution(d) => cosmwasm_std::CosmosMsg::Distribution(d), + #[cfg(feature = "staking")] + CosmosMsg::Staking(s) => cosmwasm_std::CosmosMsg::Staking(s), + CosmosMsg::Wasm(w) => cosmwasm_std::CosmosMsg::Wasm(w), + } + } +} + +impl From> for CosmosMsg +where + T: Clone + fmt::Debug + PartialEq + JsonSchema, +{ + fn from(input: cosmwasm_std::CosmosMsg) -> CosmosMsg { + match input { + cosmwasm_std::CosmosMsg::Bank(b) => CosmosMsg::Bank(b), + cosmwasm_std::CosmosMsg::Custom(c) => CosmosMsg::Custom(c), + #[cfg(feature = "staking")] + cosmwasm_std::CosmosMsg::Distribution(d) => CosmosMsg::Distribution(d), + #[cfg(feature = "staking")] + cosmwasm_std::CosmosMsg::Staking(s) => CosmosMsg::Staking(s), + cosmwasm_std::CosmosMsg::Wasm(w) => CosmosMsg::Wasm(w), + _ => panic!("Unsupported type"), + } + } +} + +impl From for CosmosMsg +where + T: Clone + fmt::Debug + PartialEq + JsonSchema, +{ + fn from(msg: BankMsg) -> Self { + CosmosMsg::Bank(msg) + } +} + +#[cfg(feature = "staking")] +impl From for CosmosMsg +where + T: Clone + fmt::Debug + PartialEq + JsonSchema, +{ + fn from(msg: StakingMsg) -> Self { + CosmosMsg::Staking(msg) + } +} + +#[cfg(feature = "staking")] +impl From for CosmosMsg +where + T: Clone + fmt::Debug + PartialEq + JsonSchema, +{ + fn from(msg: DistributionMsg) -> Self { + CosmosMsg::Distribution(msg) + } +} + +impl From for CosmosMsg +where + T: Clone + fmt::Debug + PartialEq + JsonSchema, +{ + fn from(msg: WasmMsg) -> Self { + CosmosMsg::Wasm(msg) + } +} From 7ff1c8abcfd1e3f63ba2b85f0bfe4a79b2be3fc2 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Wed, 15 Sep 2021 16:09:28 +0200 Subject: [PATCH 7/7] Simplify tests --- packages/multi-test/src/app.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/multi-test/src/app.rs b/packages/multi-test/src/app.rs index fdb78ab39..c57a04bee 100644 --- a/packages/multi-test/src/app.rs +++ b/packages/multi-test/src/app.rs @@ -665,7 +665,7 @@ mod test { app.execute(rcpt.clone(), msg).unwrap(); // cannot send too much - let msg: cosmwasm_std::CosmosMsg = BankMsg::Send { + let msg = BankMsg::Send { to_address: rcpt.into(), amount: coins(20, "btc"), } @@ -1117,12 +1117,12 @@ mod test { // cache 1 - send some tokens let mut cache = StorageTransaction::new(&app.storage); - let msg = CosmosMsg::Bank(BankMsg::Send { + let msg = BankMsg::Send { to_address: rcpt.clone().into(), amount: coins(25, "eth"), - }); + }; app.router - .execute(&app.api, &mut cache, &app.block, owner.clone(), msg) + .execute(&app.api, &mut cache, &app.block, owner.clone(), msg.into()) .unwrap(); // shows up in cache @@ -1133,12 +1133,12 @@ mod test { // now, second level cache transactional(&mut cache, |cache2, read| { - let msg = CosmosMsg::Bank(BankMsg::Send { + let msg = BankMsg::Send { to_address: rcpt.clone().into(), amount: coins(12, "eth"), - }); + }; app.router - .execute(&app.api, cache2, &app.block, owner, msg) + .execute(&app.api, cache2, &app.block, owner, msg.into()) .unwrap(); // shows up in 2nd cache