oasis_runtime_sdk/
context.rs1use std::{collections::btree_map::BTreeMap, marker::PhantomData};
3
4use slog::{self, o};
5
6use oasis_core_runtime::{
7 common::{logger::get_logger, namespace::Namespace},
8 consensus,
9 consensus::roothash,
10 protocol::HostInfo,
11};
12
13use crate::{
14 history,
15 keymanager::KeyManager,
16 module::MethodHandler as _,
17 runtime,
18 state::{self, CurrentState},
19};
20
21const LOCAL_CONFIG_ALLOW_EXPENSIVE_QUERIES: &str = "allow_expensive_queries";
25const LOCAL_CONFIG_ESTIMATE_GAS_BY_SIMULATING_CONTRACTS: &str =
28 "estimate_gas_by_simulating_contracts";
29const LOCAL_CONFIG_ALLOWED_QUERIES: &str = "allowed_queries";
31const LOCAL_CONFIG_ALLOWED_QUERIES_ALL: &str = "all";
33const LOCAL_CONFIG_ALLOWED_QUERIES_ALL_EXPENSIVE: &str = "all_expensive";
36
37pub trait Context {
39 type Runtime: runtime::Runtime;
41
42 fn clone(&self) -> Self;
44
45 fn get_logger(&self, module: &'static str) -> slog::Logger;
47
48 fn should_execute_contracts(&self) -> bool {
50 match CurrentState::with_env(|env| env.mode()) {
51 state::Mode::Execute => true,
53 state::Mode::Simulate => {
54 if let Some(allow_expensive_queries) =
56 self.local_config::<bool>(LOCAL_CONFIG_ALLOW_EXPENSIVE_QUERIES)
57 {
58 slog::warn!(
59 self.get_logger("runtime-sdk"),
60 "The {} config option is DEPRECATED since April 2022 and will be removed in a future release. Use {} and {} instead.",
61 LOCAL_CONFIG_ALLOW_EXPENSIVE_QUERIES,
62 LOCAL_CONFIG_ESTIMATE_GAS_BY_SIMULATING_CONTRACTS,
63 LOCAL_CONFIG_ALLOWED_QUERIES
64 );
65 return allow_expensive_queries;
66 };
67
68 self.local_config(LOCAL_CONFIG_ESTIMATE_GAS_BY_SIMULATING_CONTRACTS)
70 .unwrap_or_default()
71 }
72 state::Mode::Check | state::Mode::PreSchedule => false,
74 }
75 }
76
77 fn is_allowed_query<R: crate::runtime::Runtime>(&self, method: &str) -> bool {
79 let config: Vec<BTreeMap<String, bool>> = self
80 .local_config(LOCAL_CONFIG_ALLOWED_QUERIES)
81 .unwrap_or_default();
82 let is_expensive = R::Modules::is_expensive_query(method);
83
84 if let Some(allow_expensive_queries) =
86 self.local_config::<bool>(LOCAL_CONFIG_ALLOW_EXPENSIVE_QUERIES)
87 {
88 slog::warn!(
89 self.get_logger("runtime-sdk"),
90 "The {} config option is DEPRECATED since April 2022 and will be removed in a future release. Use {} and {} instead.",
91 LOCAL_CONFIG_ALLOW_EXPENSIVE_QUERIES,
92 LOCAL_CONFIG_ESTIMATE_GAS_BY_SIMULATING_CONTRACTS,
93 LOCAL_CONFIG_ALLOWED_QUERIES
94 );
95 return (!is_expensive) || allow_expensive_queries;
96 };
97
98 config
100 .iter()
101 .find_map(|item| {
102 item.get(method)
103 .or_else(|| {
104 if !is_expensive {
105 return None;
106 }
107 item.get(LOCAL_CONFIG_ALLOWED_QUERIES_ALL_EXPENSIVE)
108 })
109 .or_else(|| item.get(LOCAL_CONFIG_ALLOWED_QUERIES_ALL))
110 .copied()
111 })
112 .unwrap_or(!is_expensive)
114 }
115
116 fn local_config<T>(&self, key: &str) -> Option<T>
120 where
121 T: cbor::Decode,
122 {
123 if CurrentState::with_env(|env| env.is_execute()) {
124 return None;
125 }
126
127 self.host_info().local_config.get(key).and_then(|v| {
128 cbor::from_value(v.clone()).unwrap_or_else(|e| {
129 let msg = format!(
130 "Cannot interpret the value of \"{}\" in runtime's local config as a {}: {:?}",
131 key,
132 std::any::type_name::<T>(),
133 e
134 );
135 slog::error!(self.get_logger("runtime-sdk"), "{}", msg);
136 panic!("{}", msg);
137 })
138 })
139 }
140
141 fn host_info(&self) -> &HostInfo;
143
144 fn runtime_id(&self) -> &Namespace {
146 &self.host_info().runtime_id
147 }
148
149 fn key_manager(&self) -> Option<&dyn KeyManager>;
151
152 fn is_confidential(&self) -> bool {
154 self.key_manager().is_some()
155 }
156
157 fn runtime_header(&self) -> &roothash::Header;
159
160 fn runtime_round_results(&self) -> &roothash::RoundResults;
162
163 fn consensus_state(&self) -> &consensus::state::ConsensusState;
165
166 fn history(&self) -> &dyn history::HistoryHost;
168
169 fn epoch(&self) -> consensus::beacon::EpochTime;
171
172 fn max_messages(&self) -> u32;
174
175 fn now(&self) -> u64 {
177 self.runtime_header().timestamp
178 }
179}
180
181pub struct RuntimeBatchContext<'a, R: runtime::Runtime> {
183 host_info: &'a HostInfo,
184 key_manager: Option<Box<dyn KeyManager>>,
185 runtime_header: &'a roothash::Header,
186 runtime_round_results: &'a roothash::RoundResults,
187 consensus_state: &'a consensus::state::ConsensusState,
188 history: &'a dyn history::HistoryHost,
189 epoch: consensus::beacon::EpochTime,
190 logger: slog::Logger,
191
192 max_messages: u32,
194
195 _runtime: PhantomData<R>,
196}
197
198impl<'a, R: runtime::Runtime> RuntimeBatchContext<'a, R> {
199 #[allow(clippy::too_many_arguments)]
201 pub fn new(
202 host_info: &'a HostInfo,
203 key_manager: Option<Box<dyn KeyManager>>,
204 runtime_header: &'a roothash::Header,
205 runtime_round_results: &'a roothash::RoundResults,
206 consensus_state: &'a consensus::state::ConsensusState,
207 history: &'a dyn history::HistoryHost,
208 epoch: consensus::beacon::EpochTime,
209 max_messages: u32,
210 ) -> Self {
211 Self {
212 host_info,
213 runtime_header,
214 runtime_round_results,
215 consensus_state,
216 history,
217 epoch,
218 key_manager,
219 logger: get_logger("runtime-sdk"),
220 max_messages,
221 _runtime: PhantomData,
222 }
223 }
224}
225
226impl<R: runtime::Runtime> Context for RuntimeBatchContext<'_, R> {
227 type Runtime = R;
228
229 fn clone(&self) -> Self {
230 Self {
231 host_info: self.host_info,
232 runtime_header: self.runtime_header,
233 runtime_round_results: self.runtime_round_results,
234 consensus_state: self.consensus_state,
235 history: self.history,
236 epoch: self.epoch,
237 key_manager: self.key_manager.clone(),
238 logger: get_logger("runtime-sdk"),
239 max_messages: self.max_messages,
240 _runtime: PhantomData,
241 }
242 }
243
244 fn get_logger(&self, module: &'static str) -> slog::Logger {
245 self.logger.new(o!("sdk_module" => module))
246 }
247
248 fn host_info(&self) -> &HostInfo {
249 self.host_info
250 }
251
252 fn key_manager(&self) -> Option<&dyn KeyManager> {
253 self.key_manager.as_ref().map(Box::as_ref)
254 }
255
256 fn runtime_header(&self) -> &roothash::Header {
257 self.runtime_header
258 }
259
260 fn runtime_round_results(&self) -> &roothash::RoundResults {
261 self.runtime_round_results
262 }
263
264 fn consensus_state(&self) -> &consensus::state::ConsensusState {
265 self.consensus_state
266 }
267
268 fn history(&self) -> &dyn history::HistoryHost {
269 self.history
270 }
271
272 fn epoch(&self) -> consensus::beacon::EpochTime {
273 self.epoch
274 }
275
276 fn max_messages(&self) -> u32 {
277 self.max_messages
278 }
279}