oasis_runtime_sdk_contracts/
code.rs1use std::{
3 io::{Read, Write},
4 num::NonZeroUsize,
5 sync::Mutex,
6};
7
8use once_cell::sync::Lazy;
9
10use oasis_runtime_sdk::{
11 core::common::crypto::hash::Hash,
12 state::CurrentState,
13 storage::{self, Store},
14};
15
16use crate::{state, types, Config, Error, Module, MODULE_NAME};
17
18static CODE_CACHE: Lazy<Mutex<lru::LruCache<Hash, Vec<u8>>>> =
20 Lazy::new(|| Mutex::new(lru::LruCache::new(NonZeroUsize::new(128).unwrap())));
21
22impl<Cfg: Config> Module<Cfg> {
23 pub fn load_code(code_info: &types::Code) -> Result<Vec<u8>, Error> {
25 let mut cache = CODE_CACHE.lock().unwrap();
26 if let Some(code) = cache.get(&code_info.hash) {
27 return Ok(code.clone());
28 }
29
30 let code = CurrentState::with_store(|store| {
32 let mut store = storage::PrefixStore::new(store, &MODULE_NAME);
33 let code_store = storage::PrefixStore::new(&mut store, &state::CODE);
34 code_store
35 .get(&code_info.id.to_storage_key())
36 .ok_or_else(|| Error::CodeNotFound(code_info.id.as_u64()))
37 })?;
38
39 let mut output = Vec::with_capacity(code.len());
41 let mut decoder = snap::read::FrameDecoder::new(code.as_slice());
42 decoder.read_to_end(&mut output).unwrap();
43
44 cache.put(code_info.hash, output.clone());
46
47 Ok(output)
48 }
49
50 pub fn store_code(code_info: &types::Code, code: &[u8]) -> Result<(), Error> {
52 let mut cache = CODE_CACHE.lock().unwrap();
54 if cache.contains(&code_info.hash) {
55 cache.put(code_info.hash, code.to_vec());
56 }
57
58 let mut output = Vec::with_capacity(code.len() << 3);
60 let mut encoder = snap::write::FrameEncoder::new(&mut output);
61 encoder.write_all(code).unwrap();
62 drop(encoder); CurrentState::with_store(|store| {
65 let mut store = storage::PrefixStore::new(store, &MODULE_NAME);
66 let mut code_store = storage::PrefixStore::new(&mut store, &state::CODE);
67 code_store.insert(&code_info.id.to_storage_key(), &output);
68 });
69
70 Ok(())
71 }
72}