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    #[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            // Send log through the execution channel to the main thread
298            caller
299                .user_data_mut()
300                .runtime
301                .send_log(message.clone(), level);
302        }
303
304        // Also use tracing for native builds (and as a fallback on web)
305        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    /// Creates a new promise to check if the `key` is in storage.
316    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    /// Waits for the promise to check if the `key` is in storage.
327    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    /// Creates a new promise to check if the `keys` are in storage.
337    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    /// Waits for the promise to check if the `keys` are in storage.
348    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    /// Creates a new promise to read multiple entries from storage.
358    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    /// Waits for the promise to read multiple entries from storage.
372    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    /// Creates a new promise to read a single entry from storage.
385    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    /// Waits for the promise to read a single entry from storage.
396    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    /// Creates a new promise to search for keys that start with the `key_prefix`.
409    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    /// Waits for the promise to search for keys that start with the `key_prefix`.
420    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    /// Creates a new promise to search for entries whose keys that start with the `key_prefix`.
430    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    /// Waits for the promise to search for entries whose keys that start with the `key_prefix`.
441    #[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/// An implementation of the system API made available to contracts.
456#[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    /// Returns the authenticated owner for this execution, if there is one.
466    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    /// Returns `Some(true)` if the incoming message was rejected from the original destination and
475    /// is now bouncing back, `Some(false)` if the message is being currently being delivered to
476    /// its original destination, or [`None`] if not executing an incoming message.
477    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    /// Returns the chain ID where the current message originated from, or [`None`] if not executing
486    /// an incoming message.
487    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    /// Returns the authenticated caller ID, if the caller configured it and if the current context.
496    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    /// Schedules a message to be sent to this application on another chain.
505    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    /// Transfers an `amount` of native tokens from `source` owner account (or the current chain's
517    /// balance) to `destination`.
518    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    /// Claims an `amount` of native tokens from a `source` account to a `destination` account.
532    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    /// Approves a `spender` to withdraw an `amount` of native tokens from the `owner`'s account.
546    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    /// Transfers an `amount` of native tokens from `owner` to `destination` using `spender`'s allowance.
560    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    /// Opens a new chain, configuring it with the provided `chain_ownership`,
575    /// `application_permissions` and initial `balance` (debited from the current chain).
576    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    /// Closes the current chain. Returns an error if the application doesn't have
590    /// permission to do so.
591    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    /// Changes the ownership of the current chain. Returns an error if the application doesn't
602    /// have permission to do so.
603    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    /// Changes the application permissions for the current chain. Returns an error if the
617    /// application doesn't have permission to do so.
618    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    /// Creates a new application on the chain, based on the supplied bytecode and
636    /// parameters.
637    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    /// Creates a new data blob and returns its hash.
652    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    /// Publishes a module with contract and service bytecode and returns the module ID.
661    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    /// Calls another application.
675    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    /// Adds a new item to an event stream. Returns the new event's index in the stream.
689    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    /// Reads an event from a stream. Returns the event's value.
698    ///
699    /// Returns an error if the event doesn't exist.
700    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    /// Subscribes this application to an event stream.
714    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    /// Unsubscribes this application from an event stream.
728    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    /// Queries a service and returns the response.
742    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    /// Consume some fuel.
755    ///
756    /// This is intended for the metering instrumentation, but if the user wants to donate
757    /// some extra fuel, more power to them!
758    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    /// Returns the amount of execution fuel remaining before execution is aborted.
767    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    /// Returns the multi-leader round in which this block was validated.
776    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    /// Writes a batch of `operations` to storage.
785    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    /// Returns true if the corresponding contract uses a zero amount of storage.
797    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/// An implementation of the system API made available to services.
810#[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    /// Schedules an operation to be included in the block being built by this query.
820    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    /// Queries another application.
829    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    /// Checks if the service has exceeded its execution time limit.
842    ///
843    /// This is called by the metering instrumentation, but the fuel consumed argument is
844    /// ignored.
845    #[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}