From 5fe7be409c8b4ca83ea31f7d1f590c0169330a45 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 19 Oct 2020 18:13:09 +0200 Subject: [PATCH] Compiles using ExternRef and ExternMut stubs --- packages/cw0/src/handlers.rs | 52 +++++++++++++++++++----------------- packages/cw0/src/lib.rs | 1 + packages/cw0/src/new_std.rs | 49 +++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 24 deletions(-) create mode 100644 packages/cw0/src/new_std.rs diff --git a/packages/cw0/src/handlers.rs b/packages/cw0/src/handlers.rs index c4114f020..a9c4cfe96 100644 --- a/packages/cw0/src/handlers.rs +++ b/packages/cw0/src/handlers.rs @@ -1,13 +1,15 @@ #![allow(dead_code)] use serde::de::DeserializeOwned; -use std::cell::Cell; +use std::cell::RefCell; use std::collections::HashMap; +use crate::new_std::{ExternMut, ExternRef}; use cosmwasm_std::{ from_slice, Api, Attribute, BankMsg, Binary, BlockInfo, ContractInfo, ContractResult, - CosmosMsg, Empty, Env, Extern, HandleResponse, HumanAddr, InitResponse, MessageInfo, Querier, + CosmosMsg, Empty, Env, HandleResponse, HumanAddr, InitResponse, MessageInfo, Querier, QuerierResult, QueryRequest, Storage, SystemError, SystemResult, WasmMsg, WasmQuery, }; +use std::ops::DerefMut; /// Interface to call into a Contract pub trait Contract @@ -18,7 +20,7 @@ where { fn handle( &self, - deps: &mut Extern, + deps: ExternMut, env: Env, info: MessageInfo, msg: Vec, @@ -26,19 +28,19 @@ where fn init( &self, - deps: &mut Extern, + deps: ExternMut, env: Env, info: MessageInfo, msg: Vec, ) -> Result; - fn query(&self, deps: &Extern, env: Env, msg: Vec) -> Result; + fn query(&self, deps: ExternRef, env: Env, msg: Vec) -> Result; } type ContractFn = - fn(deps: &mut Extern, env: Env, info: MessageInfo, msg: T) -> Result; + fn(deps: ExternMut, env: Env, info: MessageInfo, msg: T) -> Result; -type QueryFn = fn(deps: &Extern, env: Env, msg: T) -> Result; +type QueryFn = fn(deps: ExternRef, env: Env, msg: T) -> Result; /// Wraps the exported functions from a contract and provides the normalized format /// TODO: Allow to customize return values (CustomMsg beyond Empty) @@ -93,7 +95,7 @@ where { fn handle( &self, - deps: &mut Extern, + deps: ExternMut, env: Env, info: MessageInfo, msg: Vec, @@ -105,7 +107,7 @@ where fn init( &self, - deps: &mut Extern, + deps: ExternMut, env: Env, info: MessageInfo, msg: Vec, @@ -115,7 +117,7 @@ where res.map_err(|e| e.to_string()) } - fn query(&self, deps: &Extern, env: Env, msg: Vec) -> Result { + fn query(&self, deps: ExternRef, env: Env, msg: Vec) -> Result { let msg: T3 = from_slice(&msg).map_err(|e| e.to_string())?; let res = (self.query_fn)(deps, env, msg); res.map_err(|e| e.to_string()) @@ -124,14 +126,14 @@ where struct ContractData { code_id: usize, - storage: Cell, + storage: RefCell, } impl ContractData { fn new(code_id: usize) -> Self { ContractData { code_id, - storage: Cell::new(S::default()), + storage: RefCell::new(S::default()), } } } @@ -195,7 +197,7 @@ where pub fn handle( &self, address: HumanAddr, - querier: Q, + querier: &Q, info: MessageInfo, msg: Vec, ) -> Result { @@ -207,7 +209,7 @@ where pub fn init( &self, address: HumanAddr, - querier: Q, + querier: &Q, info: MessageInfo, msg: Vec, ) -> Result { @@ -216,9 +218,9 @@ where }) } - pub fn query(&self, address: HumanAddr, querier: Q, msg: Vec) -> Result { + pub fn query(&self, address: HumanAddr, querier: &Q, msg: Vec) -> Result { self.with_storage(querier, address, |handler, deps, env| { - handler.query(deps, env, msg) + handler.query(deps.as_ref(), env, msg) }) } @@ -231,9 +233,9 @@ where } } - fn with_storage(&self, querier: Q, address: HumanAddr, action: F) -> Result + fn with_storage(&self, querier: &Q, address: HumanAddr, action: F) -> Result where - F: FnOnce(&Box>, &mut Extern, Env) -> Result, + F: FnOnce(&Box>, ExternMut, Env) -> Result, { let contract = self .contracts @@ -245,14 +247,16 @@ where .ok_or_else(|| "Unregistered code id".to_string())?; let env = self.get_env(address); - let storage = contract.storage.take(); - let mut deps = Extern { - storage, - api: self.api, + let mut storage = contract + .storage + .try_borrow_mut() + .map_err(|e| format!("Double-borrowing mutable storage - re-entrancy?: {}", e))?; + let deps = ExternMut { + storage: storage.deref_mut(), + api: &self.api, querier, }; - let res = action(handler, &mut deps, env); - contract.storage.replace(deps.storage); + let res = action(handler, deps, env); res } } diff --git a/packages/cw0/src/lib.rs b/packages/cw0/src/lib.rs index 69703bb88..4aa397168 100644 --- a/packages/cw0/src/lib.rs +++ b/packages/cw0/src/lib.rs @@ -1,6 +1,7 @@ mod balance; mod expiration; mod handlers; +mod new_std; mod pagination; pub use crate::balance::NativeBalance; diff --git a/packages/cw0/src/new_std.rs b/packages/cw0/src/new_std.rs new file mode 100644 index 000000000..51601278c --- /dev/null +++ b/packages/cw0/src/new_std.rs @@ -0,0 +1,49 @@ +use cosmwasm_std::{Api, Querier, Storage}; + +///! some features that should be in cosmwasm_std v0.12 mocked out here for ease + +pub struct ExternMut<'a, S: Storage, A: Api, Q: Querier> { + pub storage: &'a mut S, + pub api: &'a A, + pub querier: &'a Q, +} + +pub struct ExternRef<'a, S: Storage, A: Api, Q: Querier> { + pub storage: &'a S, + pub api: &'a A, + pub querier: &'a Q, +} + +impl<'a, S: Storage, A: Api, Q: Querier> ExternMut<'a, S, A, Q> { + pub fn as_ref(self) -> ExternRef<'a, S, A, Q> { + ExternRef { + storage: self.storage, + api: self.api, + querier: self.querier, + } + } +} + +// pub struct Extern { +// pub storage: S, +// pub api: A, +// pub querier: Q, +// } +// +// impl Extern { +// pub fn as_ref(&'_ self) -> ExternRef<'_, S, A, Q> { +// ExternRef { +// storage: &self.storage, +// api: &self.api, +// querier: &self.querier, +// } +// } +// +// pub fn as_mut(&'_ mut self) -> ExternMut<'_, S, A, Q> { +// ExternMut { +// storage: &mut self.storage, +// api: &self.api, +// querier: &self.querier, +// } +// } +// }