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