oasis_runtime_sdk_contracts/
store.rs1use oasis_contract_sdk_types::storage::StoreKind;
3use oasis_runtime_sdk::{
4 context::Context,
5 dispatcher,
6 keymanager::{self, StateKey},
7 state::CurrentState,
8 storage::{self, Store},
9 subcall,
10};
11
12use crate::{state, types, Error, MODULE_NAME};
13
14pub const CONFIDENTIAL_STORE_KEY_PAIR_ID_CONTEXT_BASE: &[u8] =
16 b"oasis-runtime-sdk/contracts: state";
17
18const CONTEXT_KEY_CONFIDENTIAL_STORE_INSTANCE_COUNT: &str = "contracts.ConfidentialStoreCounter";
19
20pub fn with_instance_store<C, F, R>(
26 ctx: &C,
27 instance_info: &types::Instance,
28 store_kind: StoreKind,
29 f: F,
30) -> Result<R, Error>
31where
32 C: Context,
33 F: FnOnce(&mut dyn Store) -> R,
34{
35 let subcall_count = if let StoreKind::Confidential = store_kind {
40 subcall::get_current_subcall_depth(ctx)
41 } else {
42 0
43 };
44 let instance_count: Option<usize> = if let StoreKind::Confidential = store_kind {
45 CurrentState::with(|state| {
46 let cnt = *state
47 .block_value(CONTEXT_KEY_CONFIDENTIAL_STORE_INSTANCE_COUNT)
48 .or_default();
49 state
50 .block_value(CONTEXT_KEY_CONFIDENTIAL_STORE_INSTANCE_COUNT)
51 .set(cnt + 1);
52 Some(cnt)
53 })
54 } else {
55 None
56 };
57 let round = ctx.runtime_header().round;
58 let confidential_key: Option<StateKey> = if let StoreKind::Confidential = store_kind {
59 let kmgr_client = ctx.key_manager().ok_or(Error::Unsupported)?;
60 let kid = keymanager::get_key_pair_id([
61 CONFIDENTIAL_STORE_KEY_PAIR_ID_CONTEXT_BASE,
62 &instance_info.id.to_storage_key(),
63 ]);
64 let kp = kmgr_client
65 .get_or_create_keys(kid)
66 .map_err(|err| Error::Abort(dispatcher::Error::KeyManagerFailure(err)))?;
67 Some(kp.state_key)
68 } else {
69 None
70 };
71
72 with_instance_raw_store(instance_info, store_kind, |contract_state| {
73 match store_kind {
74 StoreKind::Public => Ok(f(&mut storage::HashedStore::<_, blake3::Hasher>::new(
76 contract_state,
77 ))),
78
79 StoreKind::Confidential => {
80 let mut confidential_store = storage::ConfidentialStore::new_with_key(
81 contract_state,
82 confidential_key.unwrap().0,
83 &[
84 round.to_le_bytes().as_slice(),
85 subcall_count.to_le_bytes().as_slice(),
86 instance_count.unwrap().to_le_bytes().as_slice(),
87 ],
88 );
89 Ok(f(&mut confidential_store))
90 }
91 }
92 })
93}
94
95pub fn with_instance_raw_store<F, R>(
97 instance_info: &types::Instance,
98 store_kind: StoreKind,
99 f: F,
100) -> R
101where
102 F: FnOnce(&mut dyn Store) -> R,
103{
104 CurrentState::with_store(|store| {
105 let store = storage::PrefixStore::new(store, &MODULE_NAME);
106 let instance_prefix = instance_info.id.to_storage_key();
107 let contract_state = storage::PrefixStore::new(
108 storage::PrefixStore::new(store, &state::INSTANCE_STATE),
109 instance_prefix,
110 );
111
112 let mut store = storage::PrefixStore::new(contract_state, store_kind.prefix());
113 f(&mut store)
114 })
115}