1use std::{any::Any, collections::HashMap, marker::PhantomData};
5
6use linera_base::{
7 data_types::{
8 Amount, ApplicationDescription, ApplicationPermissions, BlockHeight, Bytecode,
9 SendMessageRequest, Timestamp,
10 },
11 http,
12 identifiers::{Account, AccountOwner, ApplicationId, ChainId, StreamName},
13 ownership::{ChainOwnership, ManageChainError},
14 vm::VmRuntime,
15};
16use linera_views::batch::{Batch, WriteOperation};
17use linera_witty::{wit_export, Instance, RuntimeError};
18use tracing::log;
19
20use super::WasmExecutionError;
21use crate::{BaseRuntime, ContractRuntime, DataBlobHash, ExecutionError, ModuleId, ServiceRuntime};
22
23pub struct RuntimeApiData<Runtime> {
25 runtime: Runtime,
26 active_promises: HashMap<u32, Box<dyn Any + Send + Sync>>,
27 promise_counter: u32,
28}
29
30impl<Runtime> RuntimeApiData<Runtime> {
31 pub fn new(runtime: Runtime) -> Self {
33 RuntimeApiData {
34 runtime,
35 active_promises: HashMap::new(),
36 promise_counter: 0,
37 }
38 }
39
40 pub fn runtime_mut(&mut self) -> &mut Runtime {
42 &mut self.runtime
43 }
44
45 fn register_promise<Promise>(&mut self, promise: Promise) -> u32
48 where
49 Promise: Send + Sync + 'static,
50 {
51 let id = self.promise_counter;
52
53 self.active_promises.insert(id, Box::new(promise));
54 self.promise_counter += 1;
55
56 id
57 }
58
59 fn take_promise<Promise>(&mut self, promise_id: u32) -> Result<Promise, RuntimeError>
61 where
62 Promise: Send + Sync + 'static,
63 {
64 let type_erased_promise = self
65 .active_promises
66 .remove(&promise_id)
67 .ok_or_else(|| RuntimeError::Custom(WasmExecutionError::UnknownPromise.into()))?;
68
69 type_erased_promise
70 .downcast()
71 .map(|boxed_promise| *boxed_promise)
72 .map_err(|_| RuntimeError::Custom(WasmExecutionError::IncorrectPromise.into()))
73 }
74}
75
76#[derive(Default)]
79pub struct BaseRuntimeApi<Caller>(PhantomData<Caller>);
80
81#[wit_export(package = "linera:app")]
82impl<Caller, Runtime> BaseRuntimeApi<Caller>
83where
84 Caller: Instance<UserData = RuntimeApiData<Runtime>>,
85 Runtime: BaseRuntime + 'static,
86{
87 fn get_chain_id(caller: &mut Caller) -> Result<ChainId, RuntimeError> {
89 caller
90 .user_data_mut()
91 .runtime
92 .chain_id()
93 .map_err(|error| RuntimeError::Custom(error.into()))
94 }
95
96 fn get_block_height(caller: &mut Caller) -> Result<BlockHeight, RuntimeError> {
98 caller
99 .user_data_mut()
100 .runtime
101 .block_height()
102 .map_err(|error| RuntimeError::Custom(error.into()))
103 }
104
105 fn get_application_id(caller: &mut Caller) -> Result<ApplicationId, RuntimeError> {
107 caller
108 .user_data_mut()
109 .runtime
110 .application_id()
111 .map_err(|error| RuntimeError::Custom(error.into()))
112 }
113
114 fn get_application_creator_chain_id(caller: &mut Caller) -> Result<ChainId, RuntimeError> {
116 caller
117 .user_data_mut()
118 .runtime
119 .application_creator_chain_id()
120 .map_err(|error| RuntimeError::Custom(error.into()))
121 }
122
123 fn read_application_description(
125 caller: &mut Caller,
126 application_id: ApplicationId,
127 ) -> Result<ApplicationDescription, RuntimeError> {
128 caller
129 .user_data_mut()
130 .runtime
131 .read_application_description(application_id)
132 .map_err(|error| RuntimeError::Custom(error.into()))
133 }
134
135 fn application_parameters(caller: &mut Caller) -> Result<Vec<u8>, RuntimeError> {
137 caller
138 .user_data_mut()
139 .runtime
140 .application_parameters()
141 .map_err(|error| RuntimeError::Custom(error.into()))
142 }
143
144 fn get_chain_ownership(caller: &mut Caller) -> Result<ChainOwnership, RuntimeError> {
146 caller
147 .user_data_mut()
148 .runtime
149 .chain_ownership()
150 .map_err(|error| RuntimeError::Custom(error.into()))
151 }
152
153 fn get_application_permissions(
155 caller: &mut Caller,
156 ) -> Result<ApplicationPermissions, RuntimeError> {
157 caller
158 .user_data_mut()
159 .runtime
160 .application_permissions()
161 .map_err(|error| RuntimeError::Custom(error.into()))
162 }
163
164 fn read_system_timestamp(caller: &mut Caller) -> Result<Timestamp, RuntimeError> {
166 caller
167 .user_data_mut()
168 .runtime
169 .read_system_timestamp()
170 .map_err(|error| RuntimeError::Custom(error.into()))
171 }
172
173 fn read_chain_balance(caller: &mut Caller) -> Result<Amount, RuntimeError> {
175 caller
176 .user_data_mut()
177 .runtime
178 .read_chain_balance()
179 .map_err(|error| RuntimeError::Custom(error.into()))
180 }
181
182 fn read_owner_balance(
184 caller: &mut Caller,
185 owner: AccountOwner,
186 ) -> Result<Amount, RuntimeError> {
187 caller
188 .user_data_mut()
189 .runtime
190 .read_owner_balance(owner)
191 .map_err(|error| RuntimeError::Custom(error.into()))
192 }
193
194 fn read_owner_balances(
196 caller: &mut Caller,
197 ) -> Result<Vec<(AccountOwner, Amount)>, RuntimeError> {
198 caller
199 .user_data_mut()
200 .runtime
201 .read_owner_balances()
202 .map_err(|error| RuntimeError::Custom(error.into()))
203 }
204
205 fn read_balance_owners(caller: &mut Caller) -> Result<Vec<AccountOwner>, RuntimeError> {
207 caller
208 .user_data_mut()
209 .runtime
210 .read_balance_owners()
211 .map_err(|error| RuntimeError::Custom(error.into()))
212 }
213
214 fn read_allowance(
216 caller: &mut Caller,
217 owner: AccountOwner,
218 spender: AccountOwner,
219 ) -> Result<Amount, RuntimeError> {
220 caller
221 .user_data_mut()
222 .runtime
223 .read_allowance(owner, spender)
224 .map_err(|error| RuntimeError::Custom(error.into()))
225 }
226
227 fn read_allowances(
229 caller: &mut Caller,
230 ) -> Result<Vec<(AccountOwner, AccountOwner, Amount)>, RuntimeError> {
231 caller
232 .user_data_mut()
233 .runtime
234 .read_allowances()
235 .map_err(|error| RuntimeError::Custom(error.into()))
236 }
237
238 fn perform_http_request(
240 caller: &mut Caller,
241 request: http::Request,
242 ) -> Result<http::Response, RuntimeError> {
243 caller
244 .user_data_mut()
245 .runtime
246 .perform_http_request(request)
247 .map_err(|error| RuntimeError::Custom(error.into()))
248 }
249
250 fn assert_before(caller: &mut Caller, timestamp: Timestamp) -> Result<(), RuntimeError> {
254 caller
255 .user_data_mut()
256 .runtime
257 .assert_before(timestamp)
258 .map_err(|error| RuntimeError::Custom(error.into()))
259 }
260
261 fn read_data_blob(caller: &mut Caller, hash: DataBlobHash) -> Result<Vec<u8>, RuntimeError> {
263 caller
264 .user_data_mut()
265 .runtime
266 .read_data_blob(hash)
267 .map_err(|error| RuntimeError::Custom(error.into()))
268 }
269
270 fn assert_data_blob_exists(
272 caller: &mut Caller,
273 hash: DataBlobHash,
274 ) -> Result<(), RuntimeError> {
275 caller
276 .user_data_mut()
277 .runtime
278 .assert_data_blob_exists(hash)
279 .map_err(|error| RuntimeError::Custom(error.into()))
280 }
281
282 #[allow(clippy::needless_pass_by_value)]
284 fn log(caller: &mut Caller, message: String, level: log::Level) -> Result<(), RuntimeError> {
285 let allowed = caller
286 .user_data_mut()
287 .runtime
288 .allow_application_logs()
289 .map_err(|error| RuntimeError::Custom(error.into()))?;
290
291 if !allowed {
292 return Ok(());
293 }
294
295 #[cfg(web)]
296 {
297 caller
299 .user_data_mut()
300 .runtime
301 .send_log(message.clone(), level);
302 }
303
304 match level {
306 log::Level::Trace => tracing::trace!("{message}"),
307 log::Level::Debug => tracing::debug!("{message}"),
308 log::Level::Info => tracing::info!("{message}"),
309 log::Level::Warn => tracing::warn!("{message}"),
310 log::Level::Error => tracing::error!("{message}"),
311 }
312 Ok(())
313 }
314
315 fn contains_key_new(caller: &mut Caller, key: Vec<u8>) -> Result<u32, RuntimeError> {
317 let mut data = caller.user_data_mut();
318 let promise = data
319 .runtime
320 .contains_key_new(key)
321 .map_err(|error| RuntimeError::Custom(error.into()))?;
322
323 Ok(data.register_promise(promise))
324 }
325
326 fn contains_key_wait(caller: &mut Caller, promise_id: u32) -> Result<bool, RuntimeError> {
328 let mut data = caller.user_data_mut();
329 let promise = data.take_promise(promise_id)?;
330
331 data.runtime
332 .contains_key_wait(&promise)
333 .map_err(|error| RuntimeError::Custom(error.into()))
334 }
335
336 fn contains_keys_new(caller: &mut Caller, keys: Vec<Vec<u8>>) -> Result<u32, RuntimeError> {
338 let mut data = caller.user_data_mut();
339 let promise = data
340 .runtime
341 .contains_keys_new(keys)
342 .map_err(|error| RuntimeError::Custom(error.into()))?;
343
344 Ok(data.register_promise(promise))
345 }
346
347 fn contains_keys_wait(caller: &mut Caller, promise_id: u32) -> Result<Vec<bool>, RuntimeError> {
349 let mut data = caller.user_data_mut();
350 let promise = data.take_promise(promise_id)?;
351
352 data.runtime
353 .contains_keys_wait(&promise)
354 .map_err(|error| RuntimeError::Custom(error.into()))
355 }
356
357 fn read_multi_values_bytes_new(
359 caller: &mut Caller,
360 keys: Vec<Vec<u8>>,
361 ) -> Result<u32, RuntimeError> {
362 let mut data = caller.user_data_mut();
363 let promise = data
364 .runtime
365 .read_multi_values_bytes_new(keys)
366 .map_err(|error| RuntimeError::Custom(error.into()))?;
367
368 Ok(data.register_promise(promise))
369 }
370
371 fn read_multi_values_bytes_wait(
373 caller: &mut Caller,
374 promise_id: u32,
375 ) -> Result<Vec<Option<Vec<u8>>>, RuntimeError> {
376 let mut data = caller.user_data_mut();
377 let promise = data.take_promise(promise_id)?;
378
379 data.runtime
380 .read_multi_values_bytes_wait(&promise)
381 .map_err(|error| RuntimeError::Custom(error.into()))
382 }
383
384 fn read_value_bytes_new(caller: &mut Caller, key: Vec<u8>) -> Result<u32, RuntimeError> {
386 let mut data = caller.user_data_mut();
387 let promise = data
388 .runtime
389 .read_value_bytes_new(key)
390 .map_err(|error| RuntimeError::Custom(error.into()))?;
391
392 Ok(data.register_promise(promise))
393 }
394
395 fn read_value_bytes_wait(
397 caller: &mut Caller,
398 promise_id: u32,
399 ) -> Result<Option<Vec<u8>>, RuntimeError> {
400 let mut data = caller.user_data_mut();
401 let promise = data.take_promise(promise_id)?;
402
403 data.runtime
404 .read_value_bytes_wait(&promise)
405 .map_err(|error| RuntimeError::Custom(error.into()))
406 }
407
408 fn find_keys_new(caller: &mut Caller, key_prefix: Vec<u8>) -> Result<u32, RuntimeError> {
410 let mut data = caller.user_data_mut();
411 let promise = data
412 .runtime
413 .find_keys_by_prefix_new(key_prefix)
414 .map_err(|error| RuntimeError::Custom(error.into()))?;
415
416 Ok(data.register_promise(promise))
417 }
418
419 fn find_keys_wait(caller: &mut Caller, promise_id: u32) -> Result<Vec<Vec<u8>>, RuntimeError> {
421 let mut data = caller.user_data_mut();
422 let promise = data.take_promise(promise_id)?;
423
424 data.runtime
425 .find_keys_by_prefix_wait(&promise)
426 .map_err(|error| RuntimeError::Custom(error.into()))
427 }
428
429 fn find_key_values_new(caller: &mut Caller, key_prefix: Vec<u8>) -> Result<u32, RuntimeError> {
431 let mut data = caller.user_data_mut();
432 let promise = data
433 .runtime
434 .find_key_values_by_prefix_new(key_prefix)
435 .map_err(|error| RuntimeError::Custom(error.into()))?;
436
437 Ok(data.register_promise(promise))
438 }
439
440 #[expect(clippy::type_complexity)]
442 fn find_key_values_wait(
443 caller: &mut Caller,
444 promise_id: u32,
445 ) -> Result<Vec<(Vec<u8>, Vec<u8>)>, RuntimeError> {
446 let mut data = caller.user_data_mut();
447 let promise = data.take_promise(promise_id)?;
448
449 data.runtime
450 .find_key_values_by_prefix_wait(&promise)
451 .map_err(|error| RuntimeError::Custom(error.into()))
452 }
453}
454
455#[derive(Default)]
457pub struct ContractRuntimeApi<Caller>(PhantomData<Caller>);
458
459#[wit_export(package = "linera:app")]
460impl<Caller, Runtime> ContractRuntimeApi<Caller>
461where
462 Caller: Instance<UserData = RuntimeApiData<Runtime>>,
463 Runtime: ContractRuntime + 'static,
464{
465 fn authenticated_owner(caller: &mut Caller) -> Result<Option<AccountOwner>, RuntimeError> {
467 caller
468 .user_data_mut()
469 .runtime
470 .authenticated_owner()
471 .map_err(|error| RuntimeError::Custom(error.into()))
472 }
473
474 fn message_is_bouncing(caller: &mut Caller) -> Result<Option<bool>, RuntimeError> {
478 caller
479 .user_data_mut()
480 .runtime
481 .message_is_bouncing()
482 .map_err(|error| RuntimeError::Custom(error.into()))
483 }
484
485 fn message_origin_chain_id(caller: &mut Caller) -> Result<Option<ChainId>, RuntimeError> {
488 caller
489 .user_data_mut()
490 .runtime
491 .message_origin_chain_id()
492 .map_err(|error| RuntimeError::Custom(error.into()))
493 }
494
495 fn authenticated_caller_id(caller: &mut Caller) -> Result<Option<ApplicationId>, RuntimeError> {
497 caller
498 .user_data_mut()
499 .runtime
500 .authenticated_caller_id()
501 .map_err(|error| RuntimeError::Custom(error.into()))
502 }
503
504 fn send_message(
506 caller: &mut Caller,
507 message: SendMessageRequest<Vec<u8>>,
508 ) -> Result<(), RuntimeError> {
509 caller
510 .user_data_mut()
511 .runtime
512 .send_message(message)
513 .map_err(|error| RuntimeError::Custom(error.into()))
514 }
515
516 fn transfer(
519 caller: &mut Caller,
520 source: AccountOwner,
521 destination: Account,
522 amount: Amount,
523 ) -> Result<(), RuntimeError> {
524 caller
525 .user_data_mut()
526 .runtime
527 .transfer(source, destination, amount)
528 .map_err(|error| RuntimeError::Custom(error.into()))
529 }
530
531 fn claim(
533 caller: &mut Caller,
534 source: Account,
535 destination: Account,
536 amount: Amount,
537 ) -> Result<(), RuntimeError> {
538 caller
539 .user_data_mut()
540 .runtime
541 .claim(source, destination, amount)
542 .map_err(|error| RuntimeError::Custom(error.into()))
543 }
544
545 fn approve(
547 caller: &mut Caller,
548 owner: AccountOwner,
549 spender: AccountOwner,
550 amount: Amount,
551 ) -> Result<(), RuntimeError> {
552 caller
553 .user_data_mut()
554 .runtime
555 .approve(owner, spender, amount)
556 .map_err(|error| RuntimeError::Custom(error.into()))
557 }
558
559 fn transfer_from(
561 caller: &mut Caller,
562 owner: AccountOwner,
563 spender: AccountOwner,
564 destination: Account,
565 amount: Amount,
566 ) -> Result<(), RuntimeError> {
567 caller
568 .user_data_mut()
569 .runtime
570 .transfer_from(owner, spender, destination, amount)
571 .map_err(|error| RuntimeError::Custom(error.into()))
572 }
573
574 fn open_chain(
577 caller: &mut Caller,
578 chain_ownership: ChainOwnership,
579 application_permissions: ApplicationPermissions,
580 balance: Amount,
581 ) -> Result<ChainId, RuntimeError> {
582 caller
583 .user_data_mut()
584 .runtime
585 .open_chain(chain_ownership, application_permissions, balance)
586 .map_err(|error| RuntimeError::Custom(error.into()))
587 }
588
589 fn close_chain(caller: &mut Caller) -> Result<Result<(), ManageChainError>, RuntimeError> {
592 match caller.user_data_mut().runtime.close_chain() {
593 Ok(()) => Ok(Ok(())),
594 Err(ExecutionError::UnauthorizedApplication(_)) => {
595 Ok(Err(ManageChainError::NotPermitted))
596 }
597 Err(error) => Err(RuntimeError::Custom(error.into())),
598 }
599 }
600
601 fn change_ownership(
604 caller: &mut Caller,
605 ownership: ChainOwnership,
606 ) -> Result<Result<(), ManageChainError>, RuntimeError> {
607 match caller.user_data_mut().runtime.change_ownership(ownership) {
608 Ok(()) => Ok(Ok(())),
609 Err(ExecutionError::UnauthorizedApplication(_)) => {
610 Ok(Err(ManageChainError::NotPermitted))
611 }
612 Err(error) => Err(RuntimeError::Custom(error.into())),
613 }
614 }
615
616 fn change_application_permissions(
619 caller: &mut Caller,
620 application_permissions: ApplicationPermissions,
621 ) -> Result<Result<(), ManageChainError>, RuntimeError> {
622 match caller
623 .user_data_mut()
624 .runtime
625 .change_application_permissions(application_permissions)
626 {
627 Ok(()) => Ok(Ok(())),
628 Err(ExecutionError::UnauthorizedApplication(_)) => {
629 Ok(Err(ManageChainError::NotPermitted))
630 }
631 Err(error) => Err(RuntimeError::Custom(error.into())),
632 }
633 }
634
635 fn create_application(
638 caller: &mut Caller,
639 module_id: ModuleId,
640 parameters: Vec<u8>,
641 argument: Vec<u8>,
642 required_application_ids: Vec<ApplicationId>,
643 ) -> Result<ApplicationId, RuntimeError> {
644 caller
645 .user_data_mut()
646 .runtime
647 .create_application(module_id, parameters, argument, required_application_ids)
648 .map_err(|error| RuntimeError::Custom(error.into()))
649 }
650
651 fn create_data_blob(caller: &mut Caller, bytes: Vec<u8>) -> Result<DataBlobHash, RuntimeError> {
653 caller
654 .user_data_mut()
655 .runtime
656 .create_data_blob(bytes)
657 .map_err(|error| RuntimeError::Custom(error.into()))
658 }
659
660 fn publish_module(
662 caller: &mut Caller,
663 contract: Bytecode,
664 service: Bytecode,
665 vm_runtime: VmRuntime,
666 ) -> Result<ModuleId, RuntimeError> {
667 caller
668 .user_data_mut()
669 .runtime
670 .publish_module(contract, service, vm_runtime)
671 .map_err(|error| RuntimeError::Custom(error.into()))
672 }
673
674 fn try_call_application(
676 caller: &mut Caller,
677 authenticated: bool,
678 callee_id: ApplicationId,
679 argument: Vec<u8>,
680 ) -> Result<Vec<u8>, RuntimeError> {
681 caller
682 .user_data_mut()
683 .runtime
684 .try_call_application(authenticated, callee_id, argument)
685 .map_err(|error| RuntimeError::Custom(error.into()))
686 }
687
688 fn emit(caller: &mut Caller, name: StreamName, value: Vec<u8>) -> Result<u32, RuntimeError> {
690 caller
691 .user_data_mut()
692 .runtime
693 .emit(name, value)
694 .map_err(|error| RuntimeError::Custom(error.into()))
695 }
696
697 fn read_event(
701 caller: &mut Caller,
702 chain_id: ChainId,
703 name: StreamName,
704 index: u32,
705 ) -> Result<Vec<u8>, RuntimeError> {
706 caller
707 .user_data_mut()
708 .runtime
709 .read_event(chain_id, name, index)
710 .map_err(|error| RuntimeError::Custom(error.into()))
711 }
712
713 fn subscribe_to_events(
715 caller: &mut Caller,
716 chain_id: ChainId,
717 application_id: ApplicationId,
718 name: StreamName,
719 ) -> Result<(), RuntimeError> {
720 caller
721 .user_data_mut()
722 .runtime
723 .subscribe_to_events(chain_id, application_id, name)
724 .map_err(|error| RuntimeError::Custom(error.into()))
725 }
726
727 fn unsubscribe_from_events(
729 caller: &mut Caller,
730 chain_id: ChainId,
731 application_id: ApplicationId,
732 name: StreamName,
733 ) -> Result<(), RuntimeError> {
734 caller
735 .user_data_mut()
736 .runtime
737 .unsubscribe_from_events(chain_id, application_id, name)
738 .map_err(|error| RuntimeError::Custom(error.into()))
739 }
740
741 fn query_service(
743 caller: &mut Caller,
744 application_id: ApplicationId,
745 query: Vec<u8>,
746 ) -> Result<Vec<u8>, RuntimeError> {
747 caller
748 .user_data_mut()
749 .runtime
750 .query_service(application_id, query)
751 .map_err(|error| RuntimeError::Custom(error.into()))
752 }
753
754 fn consume_fuel(caller: &mut Caller, fuel: u64) -> Result<(), RuntimeError> {
759 caller
760 .user_data_mut()
761 .runtime_mut()
762 .consume_fuel(fuel, VmRuntime::Wasm)
763 .map_err(|e| RuntimeError::Custom(e.into()))
764 }
765
766 fn remaining_fuel(caller: &mut Caller) -> Result<u64, RuntimeError> {
768 caller
769 .user_data_mut()
770 .runtime_mut()
771 .remaining_fuel(VmRuntime::Wasm)
772 .map_err(|error| RuntimeError::Custom(error.into()))
773 }
774
775 fn validation_round(caller: &mut Caller) -> Result<Option<u32>, RuntimeError> {
777 caller
778 .user_data_mut()
779 .runtime_mut()
780 .validation_round()
781 .map_err(|error| RuntimeError::Custom(error.into()))
782 }
783
784 fn write_batch(
786 caller: &mut Caller,
787 operations: Vec<WriteOperation>,
788 ) -> Result<(), RuntimeError> {
789 caller
790 .user_data_mut()
791 .runtime_mut()
792 .write_batch(Batch { operations })
793 .map_err(|error| RuntimeError::Custom(error.into()))
794 }
795
796 fn has_empty_storage(
798 caller: &mut Caller,
799 application: ApplicationId,
800 ) -> Result<bool, RuntimeError> {
801 caller
802 .user_data_mut()
803 .runtime_mut()
804 .has_empty_storage(application)
805 .map_err(|error| RuntimeError::Custom(error.into()))
806 }
807}
808
809#[derive(Default)]
811pub struct ServiceRuntimeApi<Caller>(PhantomData<Caller>);
812
813#[wit_export(package = "linera:app")]
814impl<Caller, Runtime> ServiceRuntimeApi<Caller>
815where
816 Caller: Instance<UserData = RuntimeApiData<Runtime>>,
817 Runtime: ServiceRuntime + 'static,
818{
819 fn schedule_operation(caller: &mut Caller, operation: Vec<u8>) -> Result<(), RuntimeError> {
821 caller
822 .user_data_mut()
823 .runtime
824 .schedule_operation(operation)
825 .map_err(|error| RuntimeError::Custom(error.into()))
826 }
827
828 fn try_query_application(
830 caller: &mut Caller,
831 application: ApplicationId,
832 argument: Vec<u8>,
833 ) -> Result<Vec<u8>, RuntimeError> {
834 caller
835 .user_data_mut()
836 .runtime
837 .try_query_application(application, argument)
838 .map_err(|error| RuntimeError::Custom(error.into()))
839 }
840
841 #[allow(unused_variables)]
846 fn check_execution_time(caller: &mut Caller, fuel_consumed: u64) -> Result<(), RuntimeError> {
847 caller
848 .user_data_mut()
849 .runtime_mut()
850 .check_execution_time()
851 .map_err(|error| RuntimeError::Custom(error.into()))
852 }
853}