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, 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
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) -> 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    /// 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 description of the given application.
124    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    /// Returns the application parameters provided when the application was created.
136    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    /// Retrieves the owner configuration for the current chain.
145    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    /// Retrieves the application permissions for the current chain.
154    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    /// Retrieves the current system time, i.e. the timestamp of the block in which this is called.
165    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    /// Returns the current chain balance.
174    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    /// Returns the balance of one of the accounts on this chain.
183    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    /// Returns the balances of all accounts on the chain.
195    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    /// Returns the owners of accounts on this chain.
206    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    /// Returns the allowance for a given owner-spender pair.
215    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    /// Returns all allowances on this chain.
228    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    /// Makes an HTTP request to the given URL and returns the response body.
239    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    /// Rejects the transaction if the current time at block validation is `>= timestamp`. Note
251    /// that block validation happens at or after the block timestamp, but isn't necessarily the
252    /// same.
253    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    /// Reads a data blob from storage.
262    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    /// Asserts the existence of a data blob with the given hash.
271    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    /// Logs a `message` with the provided information `level`.
283    fn log(caller: &mut Caller, message: String, level: log::Level) -> Result<(), RuntimeError> {
284        let allowed = caller
285            .user_data_mut()
286            .runtime
287            .allow_application_logs()
288            .map_err(|error| RuntimeError::Custom(error.into()))?;
289
290        if !allowed {
291            return Ok(());
292        }
293
294        #[cfg(web)]
295        {
296            // Send log through the execution channel to the main thread
297            caller
298                .user_data_mut()
299                .runtime
300                .send_log(message.clone(), level);
301        }
302
303        // Also use tracing for native builds (and as a fallback on web)
304        match level {
305            log::Level::Trace => tracing::trace!("{message}"),
306            log::Level::Debug => tracing::debug!("{message}"),
307            log::Level::Info => tracing::info!("{message}"),
308            log::Level::Warn => tracing::warn!("{message}"),
309            log::Level::Error => tracing::error!("{message}"),
310        }
311        Ok(())
312    }
313
314    /// Creates a new promise to check if the `key` is in storage.
315    fn contains_key_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            .contains_key_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 check if the `key` is in storage.
326    fn contains_key_wait(caller: &mut Caller, promise_id: u32) -> Result<bool, RuntimeError> {
327        let mut data = caller.user_data_mut();
328        let promise = data.take_promise(promise_id)?;
329
330        data.runtime
331            .contains_key_wait(&promise)
332            .map_err(|error| RuntimeError::Custom(error.into()))
333    }
334
335    /// Creates a new promise to check if the `keys` are in storage.
336    fn contains_keys_new(caller: &mut Caller, keys: Vec<Vec<u8>>) -> Result<u32, RuntimeError> {
337        let mut data = caller.user_data_mut();
338        let promise = data
339            .runtime
340            .contains_keys_new(keys)
341            .map_err(|error| RuntimeError::Custom(error.into()))?;
342
343        Ok(data.register_promise(promise))
344    }
345
346    /// Waits for the promise to check if the `keys` are in storage.
347    fn contains_keys_wait(caller: &mut Caller, promise_id: u32) -> Result<Vec<bool>, RuntimeError> {
348        let mut data = caller.user_data_mut();
349        let promise = data.take_promise(promise_id)?;
350
351        data.runtime
352            .contains_keys_wait(&promise)
353            .map_err(|error| RuntimeError::Custom(error.into()))
354    }
355
356    /// Creates a new promise to read multiple entries from storage.
357    fn read_multi_values_bytes_new(
358        caller: &mut Caller,
359        keys: Vec<Vec<u8>>,
360    ) -> Result<u32, RuntimeError> {
361        let mut data = caller.user_data_mut();
362        let promise = data
363            .runtime
364            .read_multi_values_bytes_new(keys)
365            .map_err(|error| RuntimeError::Custom(error.into()))?;
366
367        Ok(data.register_promise(promise))
368    }
369
370    /// Waits for the promise to read multiple entries from storage.
371    fn read_multi_values_bytes_wait(
372        caller: &mut Caller,
373        promise_id: u32,
374    ) -> Result<Vec<Option<Vec<u8>>>, RuntimeError> {
375        let mut data = caller.user_data_mut();
376        let promise = data.take_promise(promise_id)?;
377
378        data.runtime
379            .read_multi_values_bytes_wait(&promise)
380            .map_err(|error| RuntimeError::Custom(error.into()))
381    }
382
383    /// Creates a new promise to read a single entry from storage.
384    fn read_value_bytes_new(caller: &mut Caller, key: Vec<u8>) -> Result<u32, RuntimeError> {
385        let mut data = caller.user_data_mut();
386        let promise = data
387            .runtime
388            .read_value_bytes_new(key)
389            .map_err(|error| RuntimeError::Custom(error.into()))?;
390
391        Ok(data.register_promise(promise))
392    }
393
394    /// Waits for the promise to read a single entry from storage.
395    fn read_value_bytes_wait(
396        caller: &mut Caller,
397        promise_id: u32,
398    ) -> Result<Option<Vec<u8>>, RuntimeError> {
399        let mut data = caller.user_data_mut();
400        let promise = data.take_promise(promise_id)?;
401
402        data.runtime
403            .read_value_bytes_wait(&promise)
404            .map_err(|error| RuntimeError::Custom(error.into()))
405    }
406
407    /// Creates a new promise to search for keys that start with the `key_prefix`.
408    fn find_keys_new(caller: &mut Caller, key_prefix: Vec<u8>) -> Result<u32, RuntimeError> {
409        let mut data = caller.user_data_mut();
410        let promise = data
411            .runtime
412            .find_keys_by_prefix_new(key_prefix)
413            .map_err(|error| RuntimeError::Custom(error.into()))?;
414
415        Ok(data.register_promise(promise))
416    }
417
418    /// Waits for the promise to search for keys that start with the `key_prefix`.
419    fn find_keys_wait(caller: &mut Caller, promise_id: u32) -> Result<Vec<Vec<u8>>, RuntimeError> {
420        let mut data = caller.user_data_mut();
421        let promise = data.take_promise(promise_id)?;
422
423        data.runtime
424            .find_keys_by_prefix_wait(&promise)
425            .map_err(|error| RuntimeError::Custom(error.into()))
426    }
427
428    /// Creates a new promise to search for entries whose keys that start with the `key_prefix`.
429    fn find_key_values_new(caller: &mut Caller, key_prefix: Vec<u8>) -> Result<u32, RuntimeError> {
430        let mut data = caller.user_data_mut();
431        let promise = data
432            .runtime
433            .find_key_values_by_prefix_new(key_prefix)
434            .map_err(|error| RuntimeError::Custom(error.into()))?;
435
436        Ok(data.register_promise(promise))
437    }
438
439    /// Waits for the promise to search for entries whose keys that start with the `key_prefix`.
440    #[expect(clippy::type_complexity)]
441    fn find_key_values_wait(
442        caller: &mut Caller,
443        promise_id: u32,
444    ) -> Result<Vec<(Vec<u8>, Vec<u8>)>, RuntimeError> {
445        let mut data = caller.user_data_mut();
446        let promise = data.take_promise(promise_id)?;
447
448        data.runtime
449            .find_key_values_by_prefix_wait(&promise)
450            .map_err(|error| RuntimeError::Custom(error.into()))
451    }
452}
453
454/// An implementation of the system API made available to contracts.
455#[derive(Default)]
456pub struct ContractRuntimeApi<Caller>(PhantomData<Caller>);
457
458#[wit_export(package = "linera:app")]
459impl<Caller, Runtime> ContractRuntimeApi<Caller>
460where
461    Caller: Instance<UserData = RuntimeApiData<Runtime>>,
462    Runtime: ContractRuntime + 'static,
463{
464    /// Returns the authenticated owner for this execution, if there is one.
465    fn authenticated_owner(caller: &mut Caller) -> Result<Option<AccountOwner>, RuntimeError> {
466        caller
467            .user_data_mut()
468            .runtime
469            .authenticated_owner()
470            .map_err(|error| RuntimeError::Custom(error.into()))
471    }
472
473    /// Returns `Some(true)` if the incoming message was rejected from the original destination and
474    /// is now bouncing back, `Some(false)` if the message is being currently being delivered to
475    /// its original destination, or [`None`] if not executing an incoming message.
476    fn message_is_bouncing(caller: &mut Caller) -> Result<Option<bool>, RuntimeError> {
477        caller
478            .user_data_mut()
479            .runtime
480            .message_is_bouncing()
481            .map_err(|error| RuntimeError::Custom(error.into()))
482    }
483
484    /// Returns the chain ID where the current message originated from, or [`None`] if not executing
485    /// an incoming message.
486    fn message_origin_chain_id(caller: &mut Caller) -> Result<Option<ChainId>, RuntimeError> {
487        caller
488            .user_data_mut()
489            .runtime
490            .message_origin_chain_id()
491            .map_err(|error| RuntimeError::Custom(error.into()))
492    }
493
494    /// Returns the authenticated caller ID, if the caller configured it and if the current context.
495    fn authenticated_caller_id(caller: &mut Caller) -> Result<Option<ApplicationId>, RuntimeError> {
496        caller
497            .user_data_mut()
498            .runtime
499            .authenticated_caller_id()
500            .map_err(|error| RuntimeError::Custom(error.into()))
501    }
502
503    /// Schedules a message to be sent to this application on another chain.
504    fn send_message(
505        caller: &mut Caller,
506        message: SendMessageRequest<Vec<u8>>,
507    ) -> Result<(), RuntimeError> {
508        caller
509            .user_data_mut()
510            .runtime
511            .send_message(message)
512            .map_err(|error| RuntimeError::Custom(error.into()))
513    }
514
515    /// Transfers an `amount` of native tokens from `source` owner account (or the current chain's
516    /// balance) to `destination`.
517    fn transfer(
518        caller: &mut Caller,
519        source: AccountOwner,
520        destination: Account,
521        amount: Amount,
522    ) -> Result<(), RuntimeError> {
523        caller
524            .user_data_mut()
525            .runtime
526            .transfer(source, destination, amount)
527            .map_err(|error| RuntimeError::Custom(error.into()))
528    }
529
530    /// Claims an `amount` of native tokens from a `source` account to a `destination` account.
531    fn claim(
532        caller: &mut Caller,
533        source: Account,
534        destination: Account,
535        amount: Amount,
536    ) -> Result<(), RuntimeError> {
537        caller
538            .user_data_mut()
539            .runtime
540            .claim(source, destination, amount)
541            .map_err(|error| RuntimeError::Custom(error.into()))
542    }
543
544    /// Approves a `spender` to withdraw an `amount` of native tokens from the `owner`'s account.
545    fn approve(
546        caller: &mut Caller,
547        owner: AccountOwner,
548        spender: AccountOwner,
549        amount: Amount,
550    ) -> Result<(), RuntimeError> {
551        caller
552            .user_data_mut()
553            .runtime
554            .approve(owner, spender, amount)
555            .map_err(|error| RuntimeError::Custom(error.into()))
556    }
557
558    /// Transfers an `amount` of native tokens from `owner` to `destination` using `spender`'s allowance.
559    fn transfer_from(
560        caller: &mut Caller,
561        owner: AccountOwner,
562        spender: AccountOwner,
563        destination: Account,
564        amount: Amount,
565    ) -> Result<(), RuntimeError> {
566        caller
567            .user_data_mut()
568            .runtime
569            .transfer_from(owner, spender, destination, amount)
570            .map_err(|error| RuntimeError::Custom(error.into()))
571    }
572
573    /// Opens a new chain, configuring it with the provided `chain_ownership`,
574    /// `application_permissions` and initial `balance` (debited from the current chain).
575    fn open_chain(
576        caller: &mut Caller,
577        chain_ownership: ChainOwnership,
578        application_permissions: ApplicationPermissions,
579        balance: Amount,
580    ) -> Result<ChainId, RuntimeError> {
581        caller
582            .user_data_mut()
583            .runtime
584            .open_chain(chain_ownership, application_permissions, balance)
585            .map_err(|error| RuntimeError::Custom(error.into()))
586    }
587
588    /// Closes the current chain. Returns an error if the application doesn't have
589    /// permission to do so.
590    fn close_chain(caller: &mut Caller) -> Result<Result<(), ManageChainError>, RuntimeError> {
591        match caller.user_data_mut().runtime.close_chain() {
592            Ok(()) => Ok(Ok(())),
593            Err(ExecutionError::UnauthorizedApplication(_)) => {
594                Ok(Err(ManageChainError::NotPermitted))
595            }
596            Err(error) => Err(RuntimeError::Custom(error.into())),
597        }
598    }
599
600    /// Changes the ownership of the current chain. Returns an error if the application doesn't
601    /// have permission to do so.
602    fn change_ownership(
603        caller: &mut Caller,
604        ownership: ChainOwnership,
605    ) -> Result<Result<(), ManageChainError>, RuntimeError> {
606        match caller.user_data_mut().runtime.change_ownership(ownership) {
607            Ok(()) => Ok(Ok(())),
608            Err(ExecutionError::UnauthorizedApplication(_)) => {
609                Ok(Err(ManageChainError::NotPermitted))
610            }
611            Err(error) => Err(RuntimeError::Custom(error.into())),
612        }
613    }
614
615    /// Changes the application permissions for the current chain. Returns an error if the
616    /// application doesn't have permission to do so.
617    fn change_application_permissions(
618        caller: &mut Caller,
619        application_permissions: ApplicationPermissions,
620    ) -> Result<Result<(), ManageChainError>, RuntimeError> {
621        match caller
622            .user_data_mut()
623            .runtime
624            .change_application_permissions(application_permissions)
625        {
626            Ok(()) => Ok(Ok(())),
627            Err(ExecutionError::UnauthorizedApplication(_)) => {
628                Ok(Err(ManageChainError::NotPermitted))
629            }
630            Err(error) => Err(RuntimeError::Custom(error.into())),
631        }
632    }
633
634    /// Creates a new application on the chain, based on the supplied bytecode and
635    /// parameters.
636    fn create_application(
637        caller: &mut Caller,
638        module_id: ModuleId,
639        parameters: Vec<u8>,
640        argument: Vec<u8>,
641        required_application_ids: Vec<ApplicationId>,
642    ) -> Result<ApplicationId, RuntimeError> {
643        caller
644            .user_data_mut()
645            .runtime
646            .create_application(module_id, parameters, argument, required_application_ids)
647            .map_err(|error| RuntimeError::Custom(error.into()))
648    }
649
650    /// Creates a new data blob and returns its hash.
651    fn create_data_blob(caller: &mut Caller, bytes: Vec<u8>) -> Result<DataBlobHash, RuntimeError> {
652        caller
653            .user_data_mut()
654            .runtime
655            .create_data_blob(bytes)
656            .map_err(|error| RuntimeError::Custom(error.into()))
657    }
658
659    /// Publishes a module with contract and service bytecode and returns the module ID.
660    fn publish_module(
661        caller: &mut Caller,
662        contract: Bytecode,
663        service: Bytecode,
664        vm_runtime: VmRuntime,
665    ) -> Result<ModuleId, RuntimeError> {
666        caller
667            .user_data_mut()
668            .runtime
669            .publish_module(contract, service, vm_runtime)
670            .map_err(|error| RuntimeError::Custom(error.into()))
671    }
672
673    /// Calls another application.
674    fn try_call_application(
675        caller: &mut Caller,
676        authenticated: bool,
677        callee_id: ApplicationId,
678        argument: Vec<u8>,
679    ) -> Result<Vec<u8>, RuntimeError> {
680        caller
681            .user_data_mut()
682            .runtime
683            .try_call_application(authenticated, callee_id, argument)
684            .map_err(|error| RuntimeError::Custom(error.into()))
685    }
686
687    /// Adds a new item to an event stream. Returns the new event's index in the stream.
688    fn emit(caller: &mut Caller, name: StreamName, value: Vec<u8>) -> Result<u32, RuntimeError> {
689        caller
690            .user_data_mut()
691            .runtime
692            .emit(name, value)
693            .map_err(|error| RuntimeError::Custom(error.into()))
694    }
695
696    /// Reads an event from a stream. Returns the event's value.
697    ///
698    /// Returns an error if the event doesn't exist.
699    fn read_event(
700        caller: &mut Caller,
701        chain_id: ChainId,
702        name: StreamName,
703        index: u32,
704    ) -> Result<Vec<u8>, RuntimeError> {
705        caller
706            .user_data_mut()
707            .runtime
708            .read_event(chain_id, name, index)
709            .map_err(|error| RuntimeError::Custom(error.into()))
710    }
711
712    /// Subscribes this application to an event stream.
713    fn subscribe_to_events(
714        caller: &mut Caller,
715        chain_id: ChainId,
716        application_id: ApplicationId,
717        name: StreamName,
718    ) -> Result<(), RuntimeError> {
719        caller
720            .user_data_mut()
721            .runtime
722            .subscribe_to_events(chain_id, application_id, name)
723            .map_err(|error| RuntimeError::Custom(error.into()))
724    }
725
726    /// Unsubscribes this application from an event stream.
727    fn unsubscribe_from_events(
728        caller: &mut Caller,
729        chain_id: ChainId,
730        application_id: ApplicationId,
731        name: StreamName,
732    ) -> Result<(), RuntimeError> {
733        caller
734            .user_data_mut()
735            .runtime
736            .unsubscribe_from_events(chain_id, application_id, name)
737            .map_err(|error| RuntimeError::Custom(error.into()))
738    }
739
740    /// Queries a service and returns the response.
741    fn query_service(
742        caller: &mut Caller,
743        application_id: ApplicationId,
744        query: Vec<u8>,
745    ) -> Result<Vec<u8>, RuntimeError> {
746        caller
747            .user_data_mut()
748            .runtime
749            .query_service(application_id, query)
750            .map_err(|error| RuntimeError::Custom(error.into()))
751    }
752
753    /// Consume some fuel.
754    ///
755    /// This is intended for the metering instrumentation, but if the user wants to donate
756    /// some extra fuel, more power to them!
757    fn consume_fuel(caller: &mut Caller, fuel: u64) -> Result<(), RuntimeError> {
758        caller
759            .user_data_mut()
760            .runtime_mut()
761            .consume_fuel(fuel, VmRuntime::Wasm)
762            .map_err(|e| RuntimeError::Custom(e.into()))
763    }
764
765    /// Returns the amount of execution fuel remaining before execution is aborted.
766    fn remaining_fuel(caller: &mut Caller) -> Result<u64, RuntimeError> {
767        caller
768            .user_data_mut()
769            .runtime_mut()
770            .remaining_fuel(VmRuntime::Wasm)
771            .map_err(|error| RuntimeError::Custom(error.into()))
772    }
773
774    /// Returns the multi-leader round in which this block was validated.
775    fn validation_round(caller: &mut Caller) -> Result<Option<u32>, RuntimeError> {
776        caller
777            .user_data_mut()
778            .runtime_mut()
779            .validation_round()
780            .map_err(|error| RuntimeError::Custom(error.into()))
781    }
782
783    /// Writes a batch of `operations` to storage.
784    fn write_batch(
785        caller: &mut Caller,
786        operations: Vec<WriteOperation>,
787    ) -> Result<(), RuntimeError> {
788        caller
789            .user_data_mut()
790            .runtime_mut()
791            .write_batch(Batch { operations })
792            .map_err(|error| RuntimeError::Custom(error.into()))
793    }
794
795    /// Returns true if the corresponding contract uses a zero amount of storage.
796    fn has_empty_storage(
797        caller: &mut Caller,
798        application: ApplicationId,
799    ) -> Result<bool, RuntimeError> {
800        caller
801            .user_data_mut()
802            .runtime_mut()
803            .has_empty_storage(application)
804            .map_err(|error| RuntimeError::Custom(error.into()))
805    }
806}
807
808/// An implementation of the system API made available to services.
809#[derive(Default)]
810pub struct ServiceRuntimeApi<Caller>(PhantomData<Caller>);
811
812#[wit_export(package = "linera:app")]
813impl<Caller, Runtime> ServiceRuntimeApi<Caller>
814where
815    Caller: Instance<UserData = RuntimeApiData<Runtime>>,
816    Runtime: ServiceRuntime + 'static,
817{
818    /// Schedules an operation to be included in the block being built by this query.
819    fn schedule_operation(caller: &mut Caller, operation: Vec<u8>) -> Result<(), RuntimeError> {
820        caller
821            .user_data_mut()
822            .runtime
823            .schedule_operation(operation)
824            .map_err(|error| RuntimeError::Custom(error.into()))
825    }
826
827    /// Queries another application.
828    fn try_query_application(
829        caller: &mut Caller,
830        application: ApplicationId,
831        argument: Vec<u8>,
832    ) -> Result<Vec<u8>, RuntimeError> {
833        caller
834            .user_data_mut()
835            .runtime
836            .try_query_application(application, argument)
837            .map_err(|error| RuntimeError::Custom(error.into()))
838    }
839
840    /// Checks if the service has exceeded its execution time limit.
841    ///
842    /// This is called by the metering instrumentation, but the fuel consumed argument is
843    /// ignored.
844    #[expect(unused_variables)]
845    fn check_execution_time(caller: &mut Caller, fuel_consumed: u64) -> Result<(), RuntimeError> {
846        caller
847            .user_data_mut()
848            .runtime_mut()
849            .check_execution_time()
850            .map_err(|error| RuntimeError::Custom(error.into()))
851    }
852}