Skip to content

Commit

Permalink
Merge pull request #1411 from oasisprotocol/kostko/feature/current-st…
Browse files Browse the repository at this point in the history
…ore-subcalls

runtime-sdk: Decouple storage from Context, add thread-local store
  • Loading branch information
kostko committed Jul 14, 2023
2 parents ca630e7 + 39cc9b2 commit 7ffa8fd
Show file tree
Hide file tree
Showing 42 changed files with 2,416 additions and 1,876 deletions.
20 changes: 10 additions & 10 deletions runtime-sdk-macros/src/method_handler_derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ pub fn derive_method_handler(impl_block: syn::ItemImpl) -> TokenStream {

let query_parameters_impl = {
quote! {
fn query_parameters<C: Context>(ctx: &mut C, _args: ()) -> Result<<Self as module::Module>::Parameters, <Self as module::Module>::Error> {
Ok(Self::params(ctx.runtime_state()))
fn query_parameters<C: Context>(_ctx: &mut C, _args: ()) -> Result<<Self as module::Module>::Parameters, <Self as module::Module>::Error> {
Ok(Self::params())
}
}
};
Expand Down Expand Up @@ -486,8 +486,8 @@ mod tests {
}
}
impl<C: Cfg> MyModule<C> {
fn query_parameters<C: Context>(ctx: &mut C, _args: ()) -> Result<<Self as module::Module>::Parameters, <Self as module::Module>::Error> {
Ok(Self::params(ctx.runtime_state()))
fn query_parameters<C: Context>(_ctx: &mut C, _args: ()) -> Result<<Self as module::Module>::Parameters, <Self as module::Module>::Error> {
Ok(Self::params())
}
}
};
Expand Down Expand Up @@ -573,8 +573,8 @@ mod tests {
}
}
impl<C: Cfg> MyModule<C> {
fn query_parameters<C: Context>(ctx: &mut C, _args: ()) -> Result<<Self as module::Module>::Parameters, <Self as module::Module>::Error> {
Ok(Self::params(ctx.runtime_state()))
fn query_parameters<C: Context>(_ctx: &mut C, _args: ()) -> Result<<Self as module::Module>::Parameters, <Self as module::Module>::Error> {
Ok(Self::params())
}
#[handler(prefetch = "my_module.MyCall")]
fn prefetch_for_my_call() {}
Expand Down Expand Up @@ -650,11 +650,11 @@ mod tests {
}
impl<C: Cfg> MyModule<C> {
fn query_parameters<C: Context>(
ctx: &mut C,
_ctx: &mut C,
_args: (),
) -> Result<<Self as module::Module>::Parameters, <Self as module::Module>::Error>
{
Ok(Self::params(ctx.runtime_state()))
Ok(Self::params())
}
#[handler(query = RPC_NAME_OF_MY_QUERY)]
fn my_query() -> () {}
Expand Down Expand Up @@ -707,8 +707,8 @@ mod tests {
}
}
impl<C: Cfg> MyModule<C> {
fn query_parameters<C: Context>(ctx: &mut C, _args: ()) -> Result<<Self as module::Module>::Parameters, <Self as module::Module>::Error> {
Ok(Self::params(ctx.runtime_state()))
fn query_parameters<C: Context>(_ctx: &mut C, _args: ()) -> Result<<Self as module::Module>::Parameters, <Self as module::Module>::Error> {
Ok(Self::params())
}
#[handler(query = "my_module.MyMC")]
fn my_method_call() -> () {}
Expand Down
10 changes: 3 additions & 7 deletions runtime-sdk/modules/contracts/src/abi/oasis/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,20 +124,16 @@ fn dispatch_query<Cfg: Config, C: Context>(ctx: &mut C, query: QueryRequest) ->

/// Perform accounts API query dispatch.
fn dispatch_accounts_query<Cfg: Config, C: Context>(
ctx: &mut C,
_ctx: &mut C,
query: AccountsQuery,
) -> QueryResponse {
match query {
AccountsQuery::Balance {
address,
denomination,
} => {
let balance = Cfg::Accounts::get_balance(
ctx.runtime_state(),
address.into(),
denomination.into(),
)
.unwrap_or_default();
let balance =
Cfg::Accounts::get_balance(address.into(), denomination.into()).unwrap_or_default();

AccountsResponse::Balance { balance }.into()
}
Expand Down
38 changes: 20 additions & 18 deletions runtime-sdk/modules/contracts/src/abi/oasis/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ impl<Cfg: Config> OasisV1<Cfg> {
let value = ctx.instance.runtime().try_with_memory(
|memory| -> Result<_, wasm3::Trap> {
let key = Region::from_arg(key).as_slice(&memory)?;
Ok(get_instance_store(ec, store_kind)?.get(key))
with_instance_store(ec, store_kind, |store| store.get(key))
},
)??;

Expand Down Expand Up @@ -123,8 +123,7 @@ impl<Cfg: Config> OasisV1<Cfg> {
.try_with_memory(|memory| -> Result<(), wasm3::Trap> {
let key = Region::from_arg(key).as_slice(&memory)?;
let value = Region::from_arg(value).as_slice(&memory)?;
get_instance_store(ec, store_kind)?.insert(key, value);
Ok(())
with_instance_store(ec, store_kind, |store| store.insert(key, value))
})??;

Ok(())
Expand Down Expand Up @@ -166,8 +165,7 @@ impl<Cfg: Config> OasisV1<Cfg> {
.runtime()
.try_with_memory(|memory| -> Result<(), wasm3::Trap> {
let key = Region::from_arg(key).as_slice(&memory)?;
get_instance_store(ec, store_kind)?.remove(key);
Ok(())
with_instance_store(ec, store_kind, |store| store.remove(key))
})??;

Ok(())
Expand All @@ -178,20 +176,24 @@ impl<Cfg: Config> OasisV1<Cfg> {
}
}

/// Create a contract instance store.
fn get_instance_store<'a, C: Context>(
ec: &'a mut ExecutionContext<'_, C>,
/// Run a closure with the contract instance store.
fn with_instance_store<C, F, R>(
ec: &mut ExecutionContext<'_, C>,
store_kind: StoreKind,
) -> Result<Box<dyn Store + 'a>, wasm3::Trap> {
let instance_store = store::for_instance(ec.tx_context, ec.instance_info, store_kind);
match instance_store {
Err(err) => {
// Propagate the underlying error.
ec.aborted = Some(err);
Err(wasm3::Trap::Abort)
}
Ok(store) => Ok(store),
}
f: F,
) -> Result<R, wasm3::Trap>
where
C: Context,
F: FnOnce(&mut dyn Store) -> R,
{
store::with_instance_store(ec.tx_context, ec.instance_info, store_kind, |store| {
f(store)
})
.map_err(|err| {
// Propagate the underlying error.
ec.aborted = Some(err);
wasm3::Trap::Abort
})
}

/// Make sure that the key size is within the range specified in module parameters.
Expand Down
31 changes: 15 additions & 16 deletions runtime-sdk/modules/contracts/src/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ use std::{
use once_cell::sync::Lazy;

use oasis_runtime_sdk::{
context::Context,
core::common::crypto::hash::Hash,
storage::{self, Store},
storage::{self, CurrentStore, Store},
};

use crate::{state, types, Config, Error, Module, MODULE_NAME};
Expand All @@ -21,18 +20,20 @@ static CODE_CACHE: Lazy<Mutex<lru::LruCache<Hash, Vec<u8>>>> =

impl<Cfg: Config> Module<Cfg> {
/// Loads code with the specified code identifier.
pub fn load_code<C: Context>(ctx: &mut C, code_info: &types::Code) -> Result<Vec<u8>, Error> {
pub fn load_code(code_info: &types::Code) -> Result<Vec<u8>, Error> {
let mut cache = CODE_CACHE.lock().unwrap();
if let Some(code) = cache.get(&code_info.hash) {
return Ok(code.clone());
}

// TODO: Support local untrusted cache to avoid storage queries.
let mut store = storage::PrefixStore::new(ctx.runtime_state(), &MODULE_NAME);
let code_store = storage::PrefixStore::new(&mut store, &state::CODE);
let code = code_store
.get(&code_info.id.to_storage_key())
.ok_or_else(|| Error::CodeNotFound(code_info.id.as_u64()))?;
let code = CurrentStore::with(|store| {
let mut store = storage::PrefixStore::new(store, &MODULE_NAME);
let code_store = storage::PrefixStore::new(&mut store, &state::CODE);
code_store
.get(&code_info.id.to_storage_key())
.ok_or_else(|| Error::CodeNotFound(code_info.id.as_u64()))
})?;

// Decompress code.
let mut output = Vec::with_capacity(code.len());
Expand All @@ -46,11 +47,7 @@ impl<Cfg: Config> Module<Cfg> {
}

/// Stores code with the specified code identifier.
pub fn store_code<C: Context>(
ctx: &mut C,
code_info: &types::Code,
code: &[u8],
) -> Result<(), Error> {
pub fn store_code(code_info: &types::Code, code: &[u8]) -> Result<(), Error> {
// If the code is currently cached replace it, otherwise don't do anything.
let mut cache = CODE_CACHE.lock().unwrap();
if cache.contains(&code_info.hash) {
Expand All @@ -63,9 +60,11 @@ impl<Cfg: Config> Module<Cfg> {
encoder.write_all(code).unwrap();
drop(encoder); // Make sure data is flushed.

let mut store = storage::PrefixStore::new(ctx.runtime_state(), &MODULE_NAME);
let mut code_store = storage::PrefixStore::new(&mut store, &state::CODE);
code_store.insert(&code_info.id.to_storage_key(), &output);
CurrentStore::with(|store| {
let mut store = storage::PrefixStore::new(store, &MODULE_NAME);
let mut code_store = storage::PrefixStore::new(&mut store, &state::CODE);
code_store.insert(&code_info.id.to_storage_key(), &output);
});

Ok(())
}
Expand Down
Loading

0 comments on commit 7ffa8fd

Please sign in to comment.