1use std::{any::Any, collections::HashMap, marker::PhantomData};
5
6use linera_base::{
7 data_types::{
8 Amount, ApplicationPermissions, BlockHeight, Bytecode, SendMessageRequest, Timestamp,
9 },
10 http,
11 identifiers::{Account, AccountOwner, ApplicationId, ChainId, StreamName},
12 ownership::{ChainOwnership, ChangeApplicationPermissionsError, CloseChainError},
13 vm::VmRuntime,
14};
15use linera_views::batch::{Batch, WriteOperation};
16use linera_witty::{wit_export, Instance, RuntimeError};
17use tracing::log;
18
19use super::WasmExecutionError;
20use crate::{BaseRuntime, ContractRuntime, DataBlobHash, ExecutionError, ModuleId, ServiceRuntime};
21
22pub struct RuntimeApiData<Runtime> {
24 runtime: Runtime,
25 active_promises: HashMap<u32, Box<dyn Any + Send + Sync>>,
26 promise_counter: u32,
27}
28
29impl<Runtime> RuntimeApiData<Runtime> {
30 pub fn new(runtime: Runtime) -> Self {
32 RuntimeApiData {
33 runtime,
34 active_promises: HashMap::new(),
35 promise_counter: 0,
36 }
37 }
38
39 pub fn runtime_mut(&mut self) -> &mut Runtime {
41 &mut self.runtime
42 }
43
44 fn register_promise<Promise>(&mut self, promise: Promise) -> u32
47 where
48 Promise: Send + Sync + 'static,
49 {
50 let id = self.promise_counter;
51
52 self.active_promises.insert(id, Box::new(promise));
53 self.promise_counter += 1;
54
55 id
56 }
57
58 fn take_promise<Promise>(&mut self, promise_id: u32) -> Result<Promise, RuntimeError>
60 where
61 Promise: Send + Sync + 'static,
62 {
63 let type_erased_promise = self
64 .active_promises
65 .remove(&promise_id)
66 .ok_or_else(|| RuntimeError::Custom(WasmExecutionError::UnknownPromise.into()))?;
67
68 type_erased_promise
69 .downcast()
70 .map(|boxed_promise| *boxed_promise)
71 .map_err(|_| RuntimeError::Custom(WasmExecutionError::IncorrectPromise.into()))
72 }
73}
74
75#[derive(Default)]
78pub struct BaseRuntimeApi<Caller>(PhantomData<Caller>);
79
80#[wit_export(package = "linera:app")]
81impl<Caller, Runtime> BaseRuntimeApi<Caller>
82where
83 Caller: Instance<UserData = RuntimeApiData<Runtime>>,
84 Runtime: BaseRuntime + 'static,
85{
86 fn get_chain_id(caller: &mut Caller) -> Result<ChainId, RuntimeError> {
88 caller
89 .user_data_mut()
90 .runtime
91 .chain_id()
92 .map_err(|error| RuntimeError::Custom(error.into()))
93 }
94
95 fn get_block_height(caller: &mut Caller) -> Result<BlockHeight, RuntimeError> {
97 caller
98 .user_data_mut()
99 .runtime
100 .block_height()
101 .map_err(|error| RuntimeError::Custom(error.into()))
102 }
103
104 fn get_application_id(caller: &mut Caller) -> Result<ApplicationId, RuntimeError> {
106 caller
107 .user_data_mut()
108 .runtime
109 .application_id()
110 .map_err(|error| RuntimeError::Custom(error.into()))
111 }
112
113 fn get_application_creator_chain_id(caller: &mut Caller) -> Result<ChainId, RuntimeError> {
115 caller
116 .user_data_mut()
117 .runtime
118 .application_creator_chain_id()
119 .map_err(|error| RuntimeError::Custom(error.into()))
120 }
121
122 fn application_parameters(caller: &mut Caller) -> Result<Vec<u8>, RuntimeError> {
124 caller
125 .user_data_mut()
126 .runtime
127 .application_parameters()
128 .map_err(|error| RuntimeError::Custom(error.into()))
129 }
130
131 fn get_chain_ownership(caller: &mut Caller) -> Result<ChainOwnership, RuntimeError> {
133 caller
134 .user_data_mut()
135 .runtime
136 .chain_ownership()
137 .map_err(|error| RuntimeError::Custom(error.into()))
138 }
139
140 fn read_system_timestamp(caller: &mut Caller) -> Result<Timestamp, RuntimeError> {
142 caller
143 .user_data_mut()
144 .runtime
145 .read_system_timestamp()
146 .map_err(|error| RuntimeError::Custom(error.into()))
147 }
148
149 fn read_chain_balance(caller: &mut Caller) -> Result<Amount, RuntimeError> {
151 caller
152 .user_data_mut()
153 .runtime
154 .read_chain_balance()
155 .map_err(|error| RuntimeError::Custom(error.into()))
156 }
157
158 fn read_owner_balance(
160 caller: &mut Caller,
161 owner: AccountOwner,
162 ) -> Result<Amount, RuntimeError> {
163 caller
164 .user_data_mut()
165 .runtime
166 .read_owner_balance(owner)
167 .map_err(|error| RuntimeError::Custom(error.into()))
168 }
169
170 fn read_owner_balances(
172 caller: &mut Caller,
173 ) -> Result<Vec<(AccountOwner, Amount)>, RuntimeError> {
174 caller
175 .user_data_mut()
176 .runtime
177 .read_owner_balances()
178 .map_err(|error| RuntimeError::Custom(error.into()))
179 }
180
181 fn read_balance_owners(caller: &mut Caller) -> Result<Vec<AccountOwner>, RuntimeError> {
183 caller
184 .user_data_mut()
185 .runtime
186 .read_balance_owners()
187 .map_err(|error| RuntimeError::Custom(error.into()))
188 }
189
190 fn perform_http_request(
192 caller: &mut Caller,
193 request: http::Request,
194 ) -> Result<http::Response, RuntimeError> {
195 caller
196 .user_data_mut()
197 .runtime
198 .perform_http_request(request)
199 .map_err(|error| RuntimeError::Custom(error.into()))
200 }
201
202 fn assert_before(caller: &mut Caller, timestamp: Timestamp) -> Result<(), RuntimeError> {
206 caller
207 .user_data_mut()
208 .runtime
209 .assert_before(timestamp)
210 .map_err(|error| RuntimeError::Custom(error.into()))
211 }
212
213 fn read_data_blob(caller: &mut Caller, hash: DataBlobHash) -> Result<Vec<u8>, RuntimeError> {
215 caller
216 .user_data_mut()
217 .runtime
218 .read_data_blob(hash)
219 .map_err(|error| RuntimeError::Custom(error.into()))
220 }
221
222 fn assert_data_blob_exists(
224 caller: &mut Caller,
225 hash: DataBlobHash,
226 ) -> Result<(), RuntimeError> {
227 caller
228 .user_data_mut()
229 .runtime
230 .assert_data_blob_exists(hash)
231 .map_err(|error| RuntimeError::Custom(error.into()))
232 }
233
234 fn log(caller: &mut Caller, message: String, level: log::Level) -> Result<(), RuntimeError> {
236 let allowed = caller
237 .user_data_mut()
238 .runtime
239 .allow_application_logs()
240 .map_err(|error| RuntimeError::Custom(error.into()))?;
241
242 if !allowed {
243 return Ok(());
244 }
245
246 #[cfg(web)]
247 {
248 caller
250 .user_data_mut()
251 .runtime
252 .send_log(message.clone(), level);
253 }
254
255 match level {
257 log::Level::Trace => tracing::trace!("{message}"),
258 log::Level::Debug => tracing::debug!("{message}"),
259 log::Level::Info => tracing::info!("{message}"),
260 log::Level::Warn => tracing::warn!("{message}"),
261 log::Level::Error => tracing::error!("{message}"),
262 }
263 Ok(())
264 }
265
266 fn contains_key_new(caller: &mut Caller, key: Vec<u8>) -> Result<u32, RuntimeError> {
268 let mut data = caller.user_data_mut();
269 let promise = data
270 .runtime
271 .contains_key_new(key)
272 .map_err(|error| RuntimeError::Custom(error.into()))?;
273
274 Ok(data.register_promise(promise))
275 }
276
277 fn contains_key_wait(caller: &mut Caller, promise_id: u32) -> Result<bool, RuntimeError> {
279 let mut data = caller.user_data_mut();
280 let promise = data.take_promise(promise_id)?;
281
282 data.runtime
283 .contains_key_wait(&promise)
284 .map_err(|error| RuntimeError::Custom(error.into()))
285 }
286
287 fn contains_keys_new(caller: &mut Caller, keys: Vec<Vec<u8>>) -> Result<u32, RuntimeError> {
289 let mut data = caller.user_data_mut();
290 let promise = data
291 .runtime
292 .contains_keys_new(keys)
293 .map_err(|error| RuntimeError::Custom(error.into()))?;
294
295 Ok(data.register_promise(promise))
296 }
297
298 fn contains_keys_wait(caller: &mut Caller, promise_id: u32) -> Result<Vec<bool>, RuntimeError> {
300 let mut data = caller.user_data_mut();
301 let promise = data.take_promise(promise_id)?;
302
303 data.runtime
304 .contains_keys_wait(&promise)
305 .map_err(|error| RuntimeError::Custom(error.into()))
306 }
307
308 fn read_multi_values_bytes_new(
310 caller: &mut Caller,
311 keys: Vec<Vec<u8>>,
312 ) -> Result<u32, RuntimeError> {
313 let mut data = caller.user_data_mut();
314 let promise = data
315 .runtime
316 .read_multi_values_bytes_new(keys)
317 .map_err(|error| RuntimeError::Custom(error.into()))?;
318
319 Ok(data.register_promise(promise))
320 }
321
322 fn read_multi_values_bytes_wait(
324 caller: &mut Caller,
325 promise_id: u32,
326 ) -> Result<Vec<Option<Vec<u8>>>, RuntimeError> {
327 let mut data = caller.user_data_mut();
328 let promise = data.take_promise(promise_id)?;
329
330 data.runtime
331 .read_multi_values_bytes_wait(&promise)
332 .map_err(|error| RuntimeError::Custom(error.into()))
333 }
334
335 fn read_value_bytes_new(caller: &mut Caller, key: Vec<u8>) -> Result<u32, RuntimeError> {
337 let mut data = caller.user_data_mut();
338 let promise = data
339 .runtime
340 .read_value_bytes_new(key)
341 .map_err(|error| RuntimeError::Custom(error.into()))?;
342
343 Ok(data.register_promise(promise))
344 }
345
346 fn read_value_bytes_wait(
348 caller: &mut Caller,
349 promise_id: u32,
350 ) -> Result<Option<Vec<u8>>, RuntimeError> {
351 let mut data = caller.user_data_mut();
352 let promise = data.take_promise(promise_id)?;
353
354 data.runtime
355 .read_value_bytes_wait(&promise)
356 .map_err(|error| RuntimeError::Custom(error.into()))
357 }
358
359 fn find_keys_new(caller: &mut Caller, key_prefix: Vec<u8>) -> Result<u32, RuntimeError> {
361 let mut data = caller.user_data_mut();
362 let promise = data
363 .runtime
364 .find_keys_by_prefix_new(key_prefix)
365 .map_err(|error| RuntimeError::Custom(error.into()))?;
366
367 Ok(data.register_promise(promise))
368 }
369
370 fn find_keys_wait(caller: &mut Caller, promise_id: u32) -> Result<Vec<Vec<u8>>, RuntimeError> {
372 let mut data = caller.user_data_mut();
373 let promise = data.take_promise(promise_id)?;
374
375 data.runtime
376 .find_keys_by_prefix_wait(&promise)
377 .map_err(|error| RuntimeError::Custom(error.into()))
378 }
379
380 fn find_key_values_new(caller: &mut Caller, key_prefix: Vec<u8>) -> Result<u32, RuntimeError> {
382 let mut data = caller.user_data_mut();
383 let promise = data
384 .runtime
385 .find_key_values_by_prefix_new(key_prefix)
386 .map_err(|error| RuntimeError::Custom(error.into()))?;
387
388 Ok(data.register_promise(promise))
389 }
390
391 #[expect(clippy::type_complexity)]
393 fn find_key_values_wait(
394 caller: &mut Caller,
395 promise_id: u32,
396 ) -> Result<Vec<(Vec<u8>, Vec<u8>)>, RuntimeError> {
397 let mut data = caller.user_data_mut();
398 let promise = data.take_promise(promise_id)?;
399
400 data.runtime
401 .find_key_values_by_prefix_wait(&promise)
402 .map_err(|error| RuntimeError::Custom(error.into()))
403 }
404}
405
406#[derive(Default)]
408pub struct ContractRuntimeApi<Caller>(PhantomData<Caller>);
409
410#[wit_export(package = "linera:app")]
411impl<Caller, Runtime> ContractRuntimeApi<Caller>
412where
413 Caller: Instance<UserData = RuntimeApiData<Runtime>>,
414 Runtime: ContractRuntime + 'static,
415{
416 fn authenticated_owner(caller: &mut Caller) -> Result<Option<AccountOwner>, RuntimeError> {
418 caller
419 .user_data_mut()
420 .runtime
421 .authenticated_owner()
422 .map_err(|error| RuntimeError::Custom(error.into()))
423 }
424
425 fn message_is_bouncing(caller: &mut Caller) -> Result<Option<bool>, RuntimeError> {
429 caller
430 .user_data_mut()
431 .runtime
432 .message_is_bouncing()
433 .map_err(|error| RuntimeError::Custom(error.into()))
434 }
435
436 fn message_origin_chain_id(caller: &mut Caller) -> Result<Option<ChainId>, RuntimeError> {
439 caller
440 .user_data_mut()
441 .runtime
442 .message_origin_chain_id()
443 .map_err(|error| RuntimeError::Custom(error.into()))
444 }
445
446 fn authenticated_caller_id(caller: &mut Caller) -> Result<Option<ApplicationId>, RuntimeError> {
448 caller
449 .user_data_mut()
450 .runtime
451 .authenticated_caller_id()
452 .map_err(|error| RuntimeError::Custom(error.into()))
453 }
454
455 fn send_message(
457 caller: &mut Caller,
458 message: SendMessageRequest<Vec<u8>>,
459 ) -> Result<(), RuntimeError> {
460 caller
461 .user_data_mut()
462 .runtime
463 .send_message(message)
464 .map_err(|error| RuntimeError::Custom(error.into()))
465 }
466
467 fn transfer(
470 caller: &mut Caller,
471 source: AccountOwner,
472 destination: Account,
473 amount: Amount,
474 ) -> Result<(), RuntimeError> {
475 caller
476 .user_data_mut()
477 .runtime
478 .transfer(source, destination, amount)
479 .map_err(|error| RuntimeError::Custom(error.into()))
480 }
481
482 fn claim(
484 caller: &mut Caller,
485 source: Account,
486 destination: Account,
487 amount: Amount,
488 ) -> Result<(), RuntimeError> {
489 caller
490 .user_data_mut()
491 .runtime
492 .claim(source, destination, amount)
493 .map_err(|error| RuntimeError::Custom(error.into()))
494 }
495
496 fn open_chain(
499 caller: &mut Caller,
500 chain_ownership: ChainOwnership,
501 application_permissions: ApplicationPermissions,
502 balance: Amount,
503 ) -> Result<ChainId, RuntimeError> {
504 caller
505 .user_data_mut()
506 .runtime
507 .open_chain(chain_ownership, application_permissions, balance)
508 .map_err(|error| RuntimeError::Custom(error.into()))
509 }
510
511 fn close_chain(caller: &mut Caller) -> Result<Result<(), CloseChainError>, RuntimeError> {
514 match caller.user_data_mut().runtime.close_chain() {
515 Ok(()) => Ok(Ok(())),
516 Err(ExecutionError::UnauthorizedApplication(_)) => {
517 Ok(Err(CloseChainError::NotPermitted))
518 }
519 Err(error) => Err(RuntimeError::Custom(error.into())),
520 }
521 }
522
523 fn change_application_permissions(
526 caller: &mut Caller,
527 application_permissions: ApplicationPermissions,
528 ) -> Result<Result<(), ChangeApplicationPermissionsError>, RuntimeError> {
529 match caller
530 .user_data_mut()
531 .runtime
532 .change_application_permissions(application_permissions)
533 {
534 Ok(()) => Ok(Ok(())),
535 Err(ExecutionError::UnauthorizedApplication(_)) => {
536 Ok(Err(ChangeApplicationPermissionsError::NotPermitted))
537 }
538 Err(error) => Err(RuntimeError::Custom(error.into())),
539 }
540 }
541
542 fn create_application(
545 caller: &mut Caller,
546 module_id: ModuleId,
547 parameters: Vec<u8>,
548 argument: Vec<u8>,
549 required_application_ids: Vec<ApplicationId>,
550 ) -> Result<ApplicationId, RuntimeError> {
551 caller
552 .user_data_mut()
553 .runtime
554 .create_application(module_id, parameters, argument, required_application_ids)
555 .map_err(|error| RuntimeError::Custom(error.into()))
556 }
557
558 fn create_data_blob(caller: &mut Caller, bytes: Vec<u8>) -> Result<DataBlobHash, RuntimeError> {
560 caller
561 .user_data_mut()
562 .runtime
563 .create_data_blob(bytes)
564 .map_err(|error| RuntimeError::Custom(error.into()))
565 }
566
567 fn publish_module(
569 caller: &mut Caller,
570 contract: Bytecode,
571 service: Bytecode,
572 vm_runtime: VmRuntime,
573 ) -> Result<ModuleId, RuntimeError> {
574 caller
575 .user_data_mut()
576 .runtime
577 .publish_module(contract, service, vm_runtime)
578 .map_err(|error| RuntimeError::Custom(error.into()))
579 }
580
581 fn try_call_application(
583 caller: &mut Caller,
584 authenticated: bool,
585 callee_id: ApplicationId,
586 argument: Vec<u8>,
587 ) -> Result<Vec<u8>, RuntimeError> {
588 caller
589 .user_data_mut()
590 .runtime
591 .try_call_application(authenticated, callee_id, argument)
592 .map_err(|error| RuntimeError::Custom(error.into()))
593 }
594
595 fn emit(caller: &mut Caller, name: StreamName, value: Vec<u8>) -> Result<u32, RuntimeError> {
597 caller
598 .user_data_mut()
599 .runtime
600 .emit(name, value)
601 .map_err(|error| RuntimeError::Custom(error.into()))
602 }
603
604 fn read_event(
608 caller: &mut Caller,
609 chain_id: ChainId,
610 name: StreamName,
611 index: u32,
612 ) -> Result<Vec<u8>, RuntimeError> {
613 caller
614 .user_data_mut()
615 .runtime
616 .read_event(chain_id, name, index)
617 .map_err(|error| RuntimeError::Custom(error.into()))
618 }
619
620 fn subscribe_to_events(
622 caller: &mut Caller,
623 chain_id: ChainId,
624 application_id: ApplicationId,
625 name: StreamName,
626 ) -> Result<(), RuntimeError> {
627 caller
628 .user_data_mut()
629 .runtime
630 .subscribe_to_events(chain_id, application_id, name)
631 .map_err(|error| RuntimeError::Custom(error.into()))
632 }
633
634 fn unsubscribe_from_events(
636 caller: &mut Caller,
637 chain_id: ChainId,
638 application_id: ApplicationId,
639 name: StreamName,
640 ) -> Result<(), RuntimeError> {
641 caller
642 .user_data_mut()
643 .runtime
644 .unsubscribe_from_events(chain_id, application_id, name)
645 .map_err(|error| RuntimeError::Custom(error.into()))
646 }
647
648 fn query_service(
650 caller: &mut Caller,
651 application_id: ApplicationId,
652 query: Vec<u8>,
653 ) -> Result<Vec<u8>, RuntimeError> {
654 caller
655 .user_data_mut()
656 .runtime
657 .query_service(application_id, query)
658 .map_err(|error| RuntimeError::Custom(error.into()))
659 }
660
661 fn consume_fuel(caller: &mut Caller, fuel: u64) -> Result<(), RuntimeError> {
666 caller
667 .user_data_mut()
668 .runtime_mut()
669 .consume_fuel(fuel, VmRuntime::Wasm)
670 .map_err(|e| RuntimeError::Custom(e.into()))
671 }
672
673 fn validation_round(caller: &mut Caller) -> Result<Option<u32>, RuntimeError> {
675 caller
676 .user_data_mut()
677 .runtime_mut()
678 .validation_round()
679 .map_err(|error| RuntimeError::Custom(error.into()))
680 }
681
682 fn write_batch(
684 caller: &mut Caller,
685 operations: Vec<WriteOperation>,
686 ) -> Result<(), RuntimeError> {
687 caller
688 .user_data_mut()
689 .runtime_mut()
690 .write_batch(Batch { operations })
691 .map_err(|error| RuntimeError::Custom(error.into()))
692 }
693
694 fn has_empty_storage(
696 caller: &mut Caller,
697 application: ApplicationId,
698 ) -> Result<bool, RuntimeError> {
699 caller
700 .user_data_mut()
701 .runtime_mut()
702 .has_empty_storage(application)
703 .map_err(|error| RuntimeError::Custom(error.into()))
704 }
705}
706
707#[derive(Default)]
709pub struct ServiceRuntimeApi<Caller>(PhantomData<Caller>);
710
711#[wit_export(package = "linera:app")]
712impl<Caller, Runtime> ServiceRuntimeApi<Caller>
713where
714 Caller: Instance<UserData = RuntimeApiData<Runtime>>,
715 Runtime: ServiceRuntime + 'static,
716{
717 fn schedule_operation(caller: &mut Caller, operation: Vec<u8>) -> Result<(), RuntimeError> {
719 caller
720 .user_data_mut()
721 .runtime
722 .schedule_operation(operation)
723 .map_err(|error| RuntimeError::Custom(error.into()))
724 }
725
726 fn try_query_application(
728 caller: &mut Caller,
729 application: ApplicationId,
730 argument: Vec<u8>,
731 ) -> Result<Vec<u8>, RuntimeError> {
732 caller
733 .user_data_mut()
734 .runtime
735 .try_query_application(application, argument)
736 .map_err(|error| RuntimeError::Custom(error.into()))
737 }
738
739 fn check_execution_time(caller: &mut Caller, _fuel_consumed: u64) -> Result<(), RuntimeError> {
744 caller
745 .user_data_mut()
746 .runtime_mut()
747 .check_execution_time()
748 .map_err(|error| RuntimeError::Custom(error.into()))
749 }
750}