1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
use crate::errors::FfiResult; use cosmwasm_std::{Binary, CanonicalAddr, HumanAddr, StdResult, SystemResult}; #[cfg(feature = "iterator")] use cosmwasm_std::{Order, KV}; /// Holds all external dependencies of the contract. /// Designed to allow easy dependency injection at runtime. /// This cannot be copied or cloned since it would behave differently /// for mock storages and a bridge storage in the VM. pub struct Extern<S: Storage, A: Api, Q: Querier> { pub storage: S, pub api: A, pub querier: Q, } impl<S: Storage, A: Api, Q: Querier> Extern<S, A, Q> { /// change_querier is a helper mainly for test code when swapping out the Querier /// from the auto-generated one from mock_dependencies. This changes the type of /// Extern so replaces requires some boilerplate. pub fn change_querier<T: Querier, F: Fn(Q) -> T>(self, transform: F) -> Extern<S, A, T> { Extern { storage: self.storage, api: self.api, querier: transform(self.querier), } } } #[cfg(feature = "iterator")] pub type NextItem = (Option<KV>, u64); #[cfg(feature = "iterator")] pub trait StorageIterator { fn next(&mut self) -> FfiResult<NextItem>; /// Collects all elements, ignoring gas costs fn elements(mut self) -> FfiResult<Vec<KV>> where Self: Sized, { let mut out: Vec<KV> = Vec::new(); while let (Some(kv), _gas_used) = self.next()? { out.push(kv); } Ok(out) } } #[cfg(feature = "iterator")] impl<I: StorageIterator + ?Sized> StorageIterator for Box<I> { fn next(&mut self) -> FfiResult<NextItem> { (**self).next() } } /// Access to the VM's backend storage, i.e. the chain pub trait Storage where Self: 'static, { /// Returns Err on error. /// Returns Ok(None) when key does not exist. /// Returns Ok(Some(Vec<u8>)) when key exists. /// /// Note: Support for differentiating between a non-existent key and a key with empty value /// is not great yet and might not be possible in all backends. But we're trying to get there. fn get(&self, key: &[u8]) -> FfiResult<(Option<Vec<u8>>, u64)>; #[cfg(feature = "iterator")] /// Allows iteration over a set of key/value pairs, either forwards or backwards. /// /// The bound `start` is inclusive and `end` is exclusive. /// /// If `start` is lexicographically greater than or equal to `end`, an empty range is described, mo matter of the order. fn range<'a>( &'a self, start: Option<&[u8]>, end: Option<&[u8]>, order: Order, ) -> FfiResult<(Box<dyn StorageIterator + 'a>, u64)>; fn set(&mut self, key: &[u8], value: &[u8]) -> FfiResult<u64>; /// Removes a database entry at `key`. /// /// The current interface does not allow to differentiate between a key that existed /// before and one that didn't exist. See https://github.com/CosmWasm/cosmwasm/issues/290 fn remove(&mut self, key: &[u8]) -> FfiResult<u64>; } /// Api are callbacks to system functions defined outside of the wasm modules. /// This is a trait to allow Mocks in the test code. /// /// Currently it just supports address conversion, we could add eg. crypto functions here. /// These should all be pure (stateless) functions. If you need state, you probably want /// to use the Querier. /// /// We can use feature flags to opt-in to non-essential methods /// for backwards compatibility in systems that don't have them all. pub trait Api: Copy + Clone + Send { fn canonical_address(&self, human: &HumanAddr) -> FfiResult<CanonicalAddr>; fn human_address(&self, canonical: &CanonicalAddr) -> FfiResult<HumanAddr>; } /// A short-hand alias for the three-level query result /// 1. Passing the query message to the backend /// 2. Accessing the contract /// 3. Executing query in the contract pub type QuerierResult = FfiResult<(SystemResult<StdResult<Binary>>, u64)>; pub trait Querier { /// raw_query is all that must be implemented for the Querier. /// This allows us to pass through binary queries from one level to another without /// knowing the custom format, or we can decode it, with the knowledge of the allowed /// types. fn raw_query(&self, bin_request: &[u8]) -> QuerierResult; }