linera_execution/wasm/
runtime_api.rs

1// Copyright (c) Zefchain Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use std::{any::Any, collections::HashMap, marker::PhantomData};
5
6use linera_base::{
7    data_types::{
8        Amount, ApplicationPermissions, BlockHeight, Bytecode, SendMessageRequest, Timestamp,
9    },
10    http,
11    identifiers::{Account, AccountOwner, ApplicationId, ChainId, StreamName},
12    ownership::{ChainOwnership, ChangeApplicationPermissionsError, CloseChainError},
13    vm::VmRuntime,
14};
15use linera_views::batch::{Batch, WriteOperation};
16use linera_witty::{wit_export, Instance, RuntimeError};
17use tracing::log;
18
19use super::WasmExecutionError;
20use crate::{BaseRuntime, ContractRuntime, DataBlobHash, ExecutionError, ModuleId, ServiceRuntime};
21
22/// Common host data used as the `UserData` of the system API implementations.
23pub struct RuntimeApiData<Runtime> {
24    runtime: Runtime,
25    active_promises: HashMap<u32, Box<dyn Any + Send + Sync>>,
26    promise_counter: u32,
27}
28
29impl<Runtime> RuntimeApiData<Runtime> {
30    /// Creates a new [`RuntimeApiData`] using the provided `runtime` to execute the system APIs.
31    pub fn new(runtime: Runtime) -> Self {
32        RuntimeApiData {
33            runtime,
34            active_promises: HashMap::new(),
35            promise_counter: 0,
36        }
37    }
38
39    /// Returns a mutable reference the system API `Runtime`.
40    pub fn runtime_mut(&mut self) -> &mut Runtime {
41        &mut self.runtime
42    }
43
44    /// Registers a `promise` internally, returning an ID that is unique for the lifetime of this
45    /// [`RuntimeApiData`].
46    fn register_promise<Promise>(&mut self, promise: Promise) -> u32
47    where
48        Promise: Send + Sync + 'static,
49    {
50        let id = self.promise_counter;
51
52        self.active_promises.insert(id, Box::new(promise));
53        self.promise_counter += 1;
54
55        id
56    }
57
58    /// Returns a `Promise` registered to the provided `promise_id`.
59    fn take_promise<Promise>(&mut self, promise_id: u32) -> Result<Promise, RuntimeError>
60    where
61        Promise: Send + Sync + 'static,
62    {
63        let type_erased_promise = self
64            .active_promises
65            .remove(&promise_id)
66            .ok_or_else(|| RuntimeError::Custom(WasmExecutionError::UnknownPromise.into()))?;
67
68        type_erased_promise
69            .downcast()
70            .map(|boxed_promise| *boxed_promise)
71            .map_err(|_| RuntimeError::Custom(WasmExecutionError::IncorrectPromise.into()))
72    }
73}
74
75/// An implementation of the runtime API used to access the common behaviour and the view storage for both contracts and
76/// services.
77#[derive(Default)]
78pub struct BaseRuntimeApi<Caller>(PhantomData<Caller>);
79
80#[wit_export(package = "linera:app")]
81impl<Caller, Runtime> BaseRuntimeApi<Caller>
82where
83    Caller: Instance<UserData = RuntimeApiData<Runtime>>,
84    Runtime: BaseRuntime + 'static,
85{
86    /// Returns the ID of the current chain.
87    fn get_chain_id(caller: &mut Caller) -> Result<ChainId, RuntimeError> {
88        caller
89            .user_data_mut()
90            .runtime
91            .chain_id()
92            .map_err(|error| RuntimeError::Custom(error.into()))
93    }
94
95    /// Returns the height of the current block that is executing.
96    fn get_block_height(caller: &mut Caller) -> Result<BlockHeight, RuntimeError> {
97        caller
98            .user_data_mut()
99            .runtime
100            .block_height()
101            .map_err(|error| RuntimeError::Custom(error.into()))
102    }
103
104    /// Returns the ID of the current application.
105    fn get_application_id(caller: &mut Caller) -> Result<ApplicationId, RuntimeError> {
106        caller
107            .user_data_mut()
108            .runtime
109            .application_id()
110            .map_err(|error| RuntimeError::Custom(error.into()))
111    }
112
113    /// Returns the chain ID of the current application creator.
114    fn get_application_creator_chain_id(caller: &mut Caller) -> Result<ChainId, RuntimeError> {
115        caller
116            .user_data_mut()
117            .runtime
118            .application_creator_chain_id()
119            .map_err(|error| RuntimeError::Custom(error.into()))
120    }
121
122    /// Returns the application parameters provided when the application was created.
123    fn application_parameters(caller: &mut Caller) -> Result<Vec<u8>, RuntimeError> {
124        caller
125            .user_data_mut()
126            .runtime
127            .application_parameters()
128            .map_err(|error| RuntimeError::Custom(error.into()))
129    }
130
131    /// Retrieves the owner configuration for the current chain.
132    fn get_chain_ownership(caller: &mut Caller) -> Result<ChainOwnership, RuntimeError> {
133        caller
134            .user_data_mut()
135            .runtime
136            .chain_ownership()
137            .map_err(|error| RuntimeError::Custom(error.into()))
138    }
139
140    /// Retrieves the current system time, i.e. the timestamp of the block in which this is called.
141    fn read_system_timestamp(caller: &mut Caller) -> Result<Timestamp, RuntimeError> {
142        caller
143            .user_data_mut()
144            .runtime
145            .read_system_timestamp()
146            .map_err(|error| RuntimeError::Custom(error.into()))
147    }
148
149    /// Returns the current chain balance.
150    fn read_chain_balance(caller: &mut Caller) -> Result<Amount, RuntimeError> {
151        caller
152            .user_data_mut()
153            .runtime
154            .read_chain_balance()
155            .map_err(|error| RuntimeError::Custom(error.into()))
156    }
157
158    /// Returns the balance of one of the accounts on this chain.
159    fn read_owner_balance(
160        caller: &mut Caller,
161        owner: AccountOwner,
162    ) -> Result<Amount, RuntimeError> {
163        caller
164            .user_data_mut()
165            .runtime
166            .read_owner_balance(owner)
167            .map_err(|error| RuntimeError::Custom(error.into()))
168    }
169
170    /// Returns the balances of all accounts on the chain.
171    fn read_owner_balances(
172        caller: &mut Caller,
173    ) -> Result<Vec<(AccountOwner, Amount)>, RuntimeError> {
174        caller
175            .user_data_mut()
176            .runtime
177            .read_owner_balances()
178            .map_err(|error| RuntimeError::Custom(error.into()))
179    }
180
181    /// Returns the owners of accounts on this chain.
182    fn read_balance_owners(caller: &mut Caller) -> Result<Vec<AccountOwner>, RuntimeError> {
183        caller
184            .user_data_mut()
185            .runtime
186            .read_balance_owners()
187            .map_err(|error| RuntimeError::Custom(error.into()))
188    }
189
190    /// Makes an HTTP request to the given URL and returns the response body.
191    fn perform_http_request(
192        caller: &mut Caller,
193        request: http::Request,
194    ) -> Result<http::Response, RuntimeError> {
195        caller
196            .user_data_mut()
197            .runtime
198            .perform_http_request(request)
199            .map_err(|error| RuntimeError::Custom(error.into()))
200    }
201
202    /// Rejects the transaction if the current time at block validation is `>= timestamp`. Note
203    /// that block validation happens at or after the block timestamp, but isn't necessarily the
204    /// same.
205    fn assert_before(caller: &mut Caller, timestamp: Timestamp) -> Result<(), RuntimeError> {
206        caller
207            .user_data_mut()
208            .runtime
209            .assert_before(timestamp)
210            .map_err(|error| RuntimeError::Custom(error.into()))
211    }
212
213    /// Reads a data blob from storage.
214    fn read_data_blob(caller: &mut Caller, hash: DataBlobHash) -> Result<Vec<u8>, RuntimeError> {
215        caller
216            .user_data_mut()
217            .runtime
218            .read_data_blob(hash)
219            .map_err(|error| RuntimeError::Custom(error.into()))
220    }
221
222    /// Asserts the existence of a data blob with the given hash.
223    fn assert_data_blob_exists(
224        caller: &mut Caller,
225        hash: DataBlobHash,
226    ) -> Result<(), RuntimeError> {
227        caller
228            .user_data_mut()
229            .runtime
230            .assert_data_blob_exists(hash)
231            .map_err(|error| RuntimeError::Custom(error.into()))
232    }
233
234    /// Logs a `message` with the provided information `level`.
235    fn log(_caller: &mut Caller, message: String, level: log::Level) {
236        match level {
237            log::Level::Trace => tracing::trace!("{message}"),
238            log::Level::Debug => tracing::debug!("{message}"),
239            log::Level::Info => tracing::info!("{message}"),
240            log::Level::Warn => tracing::warn!("{message}"),
241            log::Level::Error => tracing::error!("{message}"),
242        }
243    }
244
245    /// Creates a new promise to check if the `key` is in storage.
246    fn contains_key_new(caller: &mut Caller, key: Vec<u8>) -> Result<u32, RuntimeError> {
247        let mut data = caller.user_data_mut();
248        let promise = data
249            .runtime
250            .contains_key_new(key)
251            .map_err(|error| RuntimeError::Custom(error.into()))?;
252
253        Ok(data.register_promise(promise))
254    }
255
256    /// Waits for the promise to check if the `key` is in storage.
257    fn contains_key_wait(caller: &mut Caller, promise_id: u32) -> Result<bool, RuntimeError> {
258        let mut data = caller.user_data_mut();
259        let promise = data.take_promise(promise_id)?;
260
261        data.runtime
262            .contains_key_wait(&promise)
263            .map_err(|error| RuntimeError::Custom(error.into()))
264    }
265
266    /// Creates a new promise to check if the `keys` are in storage.
267    fn contains_keys_new(caller: &mut Caller, keys: Vec<Vec<u8>>) -> Result<u32, RuntimeError> {
268        let mut data = caller.user_data_mut();
269        let promise = data
270            .runtime
271            .contains_keys_new(keys)
272            .map_err(|error| RuntimeError::Custom(error.into()))?;
273
274        Ok(data.register_promise(promise))
275    }
276
277    /// Waits for the promise to check if the `keys` are in storage.
278    fn contains_keys_wait(caller: &mut Caller, promise_id: u32) -> Result<Vec<bool>, RuntimeError> {
279        let mut data = caller.user_data_mut();
280        let promise = data.take_promise(promise_id)?;
281
282        data.runtime
283            .contains_keys_wait(&promise)
284            .map_err(|error| RuntimeError::Custom(error.into()))
285    }
286
287    /// Creates a new promise to read multiple entries from storage.
288    fn read_multi_values_bytes_new(
289        caller: &mut Caller,
290        keys: Vec<Vec<u8>>,
291    ) -> Result<u32, RuntimeError> {
292        let mut data = caller.user_data_mut();
293        let promise = data
294            .runtime
295            .read_multi_values_bytes_new(keys)
296            .map_err(|error| RuntimeError::Custom(error.into()))?;
297
298        Ok(data.register_promise(promise))
299    }
300
301    /// Waits for the promise to read multiple entries from storage.
302    fn read_multi_values_bytes_wait(
303        caller: &mut Caller,
304        promise_id: u32,
305    ) -> Result<Vec<Option<Vec<u8>>>, RuntimeError> {
306        let mut data = caller.user_data_mut();
307        let promise = data.take_promise(promise_id)?;
308
309        data.runtime
310            .read_multi_values_bytes_wait(&promise)
311            .map_err(|error| RuntimeError::Custom(error.into()))
312    }
313
314    /// Creates a new promise to read a single entry from storage.
315    fn read_value_bytes_new(caller: &mut Caller, key: Vec<u8>) -> Result<u32, RuntimeError> {
316        let mut data = caller.user_data_mut();
317        let promise = data
318            .runtime
319            .read_value_bytes_new(key)
320            .map_err(|error| RuntimeError::Custom(error.into()))?;
321
322        Ok(data.register_promise(promise))
323    }
324
325    /// Waits for the promise to read a single entry from storage.
326    fn read_value_bytes_wait(
327        caller: &mut Caller,
328        promise_id: u32,
329    ) -> Result<Option<Vec<u8>>, RuntimeError> {
330        let mut data = caller.user_data_mut();
331        let promise = data.take_promise(promise_id)?;
332
333        data.runtime
334            .read_value_bytes_wait(&promise)
335            .map_err(|error| RuntimeError::Custom(error.into()))
336    }
337
338    /// Creates a new promise to search for keys that start with the `key_prefix`.
339    fn find_keys_new(caller: &mut Caller, key_prefix: Vec<u8>) -> Result<u32, RuntimeError> {
340        let mut data = caller.user_data_mut();
341        let promise = data
342            .runtime
343            .find_keys_by_prefix_new(key_prefix)
344            .map_err(|error| RuntimeError::Custom(error.into()))?;
345
346        Ok(data.register_promise(promise))
347    }
348
349    /// Waits for the promise to search for keys that start with the `key_prefix`.
350    fn find_keys_wait(caller: &mut Caller, promise_id: u32) -> Result<Vec<Vec<u8>>, RuntimeError> {
351        let mut data = caller.user_data_mut();
352        let promise = data.take_promise(promise_id)?;
353
354        data.runtime
355            .find_keys_by_prefix_wait(&promise)
356            .map_err(|error| RuntimeError::Custom(error.into()))
357    }
358
359    /// Creates a new promise to search for entries whose keys that start with the `key_prefix`.
360    fn find_key_values_new(caller: &mut Caller, key_prefix: Vec<u8>) -> Result<u32, RuntimeError> {
361        let mut data = caller.user_data_mut();
362        let promise = data
363            .runtime
364            .find_key_values_by_prefix_new(key_prefix)
365            .map_err(|error| RuntimeError::Custom(error.into()))?;
366
367        Ok(data.register_promise(promise))
368    }
369
370    /// Waits for the promise to search for entries whose keys that start with the `key_prefix`.
371    #[expect(clippy::type_complexity)]
372    fn find_key_values_wait(
373        caller: &mut Caller,
374        promise_id: u32,
375    ) -> Result<Vec<(Vec<u8>, Vec<u8>)>, RuntimeError> {
376        let mut data = caller.user_data_mut();
377        let promise = data.take_promise(promise_id)?;
378
379        data.runtime
380            .find_key_values_by_prefix_wait(&promise)
381            .map_err(|error| RuntimeError::Custom(error.into()))
382    }
383}
384
385/// An implementation of the system API made available to contracts.
386#[derive(Default)]
387pub struct ContractRuntimeApi<Caller>(PhantomData<Caller>);
388
389#[wit_export(package = "linera:app")]
390impl<Caller, Runtime> ContractRuntimeApi<Caller>
391where
392    Caller: Instance<UserData = RuntimeApiData<Runtime>>,
393    Runtime: ContractRuntime + 'static,
394{
395    /// Returns the authenticated owner for this execution, if there is one.
396    fn authenticated_owner(caller: &mut Caller) -> Result<Option<AccountOwner>, RuntimeError> {
397        caller
398            .user_data_mut()
399            .runtime
400            .authenticated_owner()
401            .map_err(|error| RuntimeError::Custom(error.into()))
402    }
403
404    /// Returns `Some(true)` if the incoming message was rejected from the original destination and
405    /// is now bouncing back, `Some(false)` if the message is being currently being delivered to
406    /// its original destination, or [`None`] if not executing an incoming message.
407    fn message_is_bouncing(caller: &mut Caller) -> Result<Option<bool>, RuntimeError> {
408        caller
409            .user_data_mut()
410            .runtime
411            .message_is_bouncing()
412            .map_err(|error| RuntimeError::Custom(error.into()))
413    }
414
415    /// Returns the chain ID where the current message originated from, or [`None`] if not executing
416    /// an incoming message.
417    fn message_origin_chain_id(caller: &mut Caller) -> Result<Option<ChainId>, RuntimeError> {
418        caller
419            .user_data_mut()
420            .runtime
421            .message_origin_chain_id()
422            .map_err(|error| RuntimeError::Custom(error.into()))
423    }
424
425    /// Returns the authenticated caller ID, if the caller configured it and if the current context.
426    fn authenticated_caller_id(caller: &mut Caller) -> Result<Option<ApplicationId>, RuntimeError> {
427        caller
428            .user_data_mut()
429            .runtime
430            .authenticated_caller_id()
431            .map_err(|error| RuntimeError::Custom(error.into()))
432    }
433
434    /// Schedules a message to be sent to this application on another chain.
435    fn send_message(
436        caller: &mut Caller,
437        message: SendMessageRequest<Vec<u8>>,
438    ) -> Result<(), RuntimeError> {
439        caller
440            .user_data_mut()
441            .runtime
442            .send_message(message)
443            .map_err(|error| RuntimeError::Custom(error.into()))
444    }
445
446    /// Transfers an `amount` of native tokens from `source` owner account (or the current chain's
447    /// balance) to `destination`.
448    fn transfer(
449        caller: &mut Caller,
450        source: AccountOwner,
451        destination: Account,
452        amount: Amount,
453    ) -> Result<(), RuntimeError> {
454        caller
455            .user_data_mut()
456            .runtime
457            .transfer(source, destination, amount)
458            .map_err(|error| RuntimeError::Custom(error.into()))
459    }
460
461    /// Claims an `amount` of native tokens from a `source` account to a `destination` account.
462    fn claim(
463        caller: &mut Caller,
464        source: Account,
465        destination: Account,
466        amount: Amount,
467    ) -> Result<(), RuntimeError> {
468        caller
469            .user_data_mut()
470            .runtime
471            .claim(source, destination, amount)
472            .map_err(|error| RuntimeError::Custom(error.into()))
473    }
474
475    /// Opens a new chain, configuring it with the provided `chain_ownership`,
476    /// `application_permissions` and initial `balance` (debited from the current chain).
477    fn open_chain(
478        caller: &mut Caller,
479        chain_ownership: ChainOwnership,
480        application_permissions: ApplicationPermissions,
481        balance: Amount,
482    ) -> Result<ChainId, RuntimeError> {
483        caller
484            .user_data_mut()
485            .runtime
486            .open_chain(chain_ownership, application_permissions, balance)
487            .map_err(|error| RuntimeError::Custom(error.into()))
488    }
489
490    /// Closes the current chain. Returns an error if the application doesn't have
491    /// permission to do so.
492    fn close_chain(caller: &mut Caller) -> Result<Result<(), CloseChainError>, RuntimeError> {
493        match caller.user_data_mut().runtime.close_chain() {
494            Ok(()) => Ok(Ok(())),
495            Err(ExecutionError::UnauthorizedApplication(_)) => {
496                Ok(Err(CloseChainError::NotPermitted))
497            }
498            Err(error) => Err(RuntimeError::Custom(error.into())),
499        }
500    }
501
502    /// Changes the application permissions for the current chain. Returns an error if the
503    /// application doesn't have permission to do so.
504    fn change_application_permissions(
505        caller: &mut Caller,
506        application_permissions: ApplicationPermissions,
507    ) -> Result<Result<(), ChangeApplicationPermissionsError>, RuntimeError> {
508        match caller
509            .user_data_mut()
510            .runtime
511            .change_application_permissions(application_permissions)
512        {
513            Ok(()) => Ok(Ok(())),
514            Err(ExecutionError::UnauthorizedApplication(_)) => {
515                Ok(Err(ChangeApplicationPermissionsError::NotPermitted))
516            }
517            Err(error) => Err(RuntimeError::Custom(error.into())),
518        }
519    }
520
521    /// Creates a new application on the chain, based on the supplied bytecode and
522    /// parameters.
523    fn create_application(
524        caller: &mut Caller,
525        module_id: ModuleId,
526        parameters: Vec<u8>,
527        argument: Vec<u8>,
528        required_application_ids: Vec<ApplicationId>,
529    ) -> Result<ApplicationId, RuntimeError> {
530        caller
531            .user_data_mut()
532            .runtime
533            .create_application(module_id, parameters, argument, required_application_ids)
534            .map_err(|error| RuntimeError::Custom(error.into()))
535    }
536
537    /// Creates a new data blob and returns its hash.
538    fn create_data_blob(caller: &mut Caller, bytes: Vec<u8>) -> Result<DataBlobHash, RuntimeError> {
539        caller
540            .user_data_mut()
541            .runtime
542            .create_data_blob(bytes)
543            .map_err(|error| RuntimeError::Custom(error.into()))
544    }
545
546    /// Publishes a module with contract and service bytecode and returns the module ID.
547    fn publish_module(
548        caller: &mut Caller,
549        contract: Bytecode,
550        service: Bytecode,
551        vm_runtime: VmRuntime,
552    ) -> Result<ModuleId, RuntimeError> {
553        caller
554            .user_data_mut()
555            .runtime
556            .publish_module(contract, service, vm_runtime)
557            .map_err(|error| RuntimeError::Custom(error.into()))
558    }
559
560    /// Calls another application.
561    fn try_call_application(
562        caller: &mut Caller,
563        authenticated: bool,
564        callee_id: ApplicationId,
565        argument: Vec<u8>,
566    ) -> Result<Vec<u8>, RuntimeError> {
567        caller
568            .user_data_mut()
569            .runtime
570            .try_call_application(authenticated, callee_id, argument)
571            .map_err(|error| RuntimeError::Custom(error.into()))
572    }
573
574    /// Adds a new item to an event stream. Returns the new event's index in the stream.
575    fn emit(caller: &mut Caller, name: StreamName, value: Vec<u8>) -> Result<u32, RuntimeError> {
576        caller
577            .user_data_mut()
578            .runtime
579            .emit(name, value)
580            .map_err(|error| RuntimeError::Custom(error.into()))
581    }
582
583    /// Reads an event from a stream. Returns the event's value.
584    ///
585    /// Returns an error if the event doesn't exist.
586    fn read_event(
587        caller: &mut Caller,
588        chain_id: ChainId,
589        name: StreamName,
590        index: u32,
591    ) -> Result<Vec<u8>, RuntimeError> {
592        caller
593            .user_data_mut()
594            .runtime
595            .read_event(chain_id, name, index)
596            .map_err(|error| RuntimeError::Custom(error.into()))
597    }
598
599    /// Subscribes this application to an event stream.
600    fn subscribe_to_events(
601        caller: &mut Caller,
602        chain_id: ChainId,
603        application_id: ApplicationId,
604        name: StreamName,
605    ) -> Result<(), RuntimeError> {
606        caller
607            .user_data_mut()
608            .runtime
609            .subscribe_to_events(chain_id, application_id, name)
610            .map_err(|error| RuntimeError::Custom(error.into()))
611    }
612
613    /// Unsubscribes this application from an event stream.
614    fn unsubscribe_from_events(
615        caller: &mut Caller,
616        chain_id: ChainId,
617        application_id: ApplicationId,
618        name: StreamName,
619    ) -> Result<(), RuntimeError> {
620        caller
621            .user_data_mut()
622            .runtime
623            .unsubscribe_from_events(chain_id, application_id, name)
624            .map_err(|error| RuntimeError::Custom(error.into()))
625    }
626
627    /// Queries a service and returns the response.
628    fn query_service(
629        caller: &mut Caller,
630        application_id: ApplicationId,
631        query: Vec<u8>,
632    ) -> Result<Vec<u8>, RuntimeError> {
633        caller
634            .user_data_mut()
635            .runtime
636            .query_service(application_id, query)
637            .map_err(|error| RuntimeError::Custom(error.into()))
638    }
639
640    /// Consume some fuel.
641    ///
642    /// This is intended for the metering instrumentation, but if the user wants to donate
643    /// some extra fuel, more power to them!
644    fn consume_fuel(caller: &mut Caller, fuel: u64) -> Result<(), RuntimeError> {
645        caller
646            .user_data_mut()
647            .runtime_mut()
648            .consume_fuel(fuel, VmRuntime::Wasm)
649            .map_err(|e| RuntimeError::Custom(e.into()))
650    }
651
652    /// Returns the round in which this block was validated.
653    fn validation_round(caller: &mut Caller) -> Result<Option<u32>, RuntimeError> {
654        caller
655            .user_data_mut()
656            .runtime_mut()
657            .validation_round()
658            .map_err(|error| RuntimeError::Custom(error.into()))
659    }
660
661    /// Writes a batch of `operations` to storage.
662    fn write_batch(
663        caller: &mut Caller,
664        operations: Vec<WriteOperation>,
665    ) -> Result<(), RuntimeError> {
666        caller
667            .user_data_mut()
668            .runtime_mut()
669            .write_batch(Batch { operations })
670            .map_err(|error| RuntimeError::Custom(error.into()))
671    }
672}
673
674/// An implementation of the system API made available to services.
675#[derive(Default)]
676pub struct ServiceRuntimeApi<Caller>(PhantomData<Caller>);
677
678#[wit_export(package = "linera:app")]
679impl<Caller, Runtime> ServiceRuntimeApi<Caller>
680where
681    Caller: Instance<UserData = RuntimeApiData<Runtime>>,
682    Runtime: ServiceRuntime + 'static,
683{
684    /// Schedules an operation to be included in the block being built by this query.
685    fn schedule_operation(caller: &mut Caller, operation: Vec<u8>) -> Result<(), RuntimeError> {
686        caller
687            .user_data_mut()
688            .runtime
689            .schedule_operation(operation)
690            .map_err(|error| RuntimeError::Custom(error.into()))
691    }
692
693    /// Queries another application.
694    fn try_query_application(
695        caller: &mut Caller,
696        application: ApplicationId,
697        argument: Vec<u8>,
698    ) -> Result<Vec<u8>, RuntimeError> {
699        caller
700            .user_data_mut()
701            .runtime
702            .try_query_application(application, argument)
703            .map_err(|error| RuntimeError::Custom(error.into()))
704    }
705
706    /// Checks if the service has exceeded its execution time limit.
707    ///
708    /// This is called by the metering instrumentation, but the fuel consumed argument is
709    /// ignored.
710    fn check_execution_time(caller: &mut Caller, _fuel_consumed: u64) -> Result<(), RuntimeError> {
711        caller
712            .user_data_mut()
713            .runtime_mut()
714            .check_execution_time()
715            .map_err(|error| RuntimeError::Custom(error.into()))
716    }
717}