Skip to main content

linera_execution/
runtime.rs

1// Copyright (c) Zefchain Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use std::{
5    collections::{hash_map, BTreeMap, HashMap, HashSet},
6    mem,
7    ops::{Deref, DerefMut},
8    sync::{Arc, Mutex},
9};
10
11use custom_debug_derive::Debug;
12use linera_base::{
13    data_types::{
14        Amount, ApplicationPermissions, ArithmeticError, Blob, BlockHeight, Bytecode,
15        SendMessageRequest, Timestamp,
16    },
17    ensure, http,
18    identifiers::{
19        Account, AccountOwner, ChainId, EventId, GenericApplicationId, StreamId, StreamName,
20    },
21    ownership::ChainOwnership,
22    time::Instant,
23    vm::VmRuntime,
24};
25use linera_views::batch::Batch;
26use oneshot::Receiver;
27use tracing::instrument;
28
29use crate::{
30    execution::UserAction,
31    execution_state_actor::{ExecutionRequest, ExecutionStateSender},
32    resources::ResourceController,
33    system::CreateApplicationResult,
34    util::{ReceiverExt, UnboundedSenderExt},
35    ApplicationDescription, ApplicationId, BaseRuntime, ContractRuntime, DataBlobHash,
36    ExecutionError, FinalizeContext, Message, MessageContext, MessageKind, ModuleId, Operation,
37    OutgoingMessage, QueryContext, QueryOutcome, ServiceRuntime, UserContractCode,
38    UserContractInstance, UserServiceCode, UserServiceInstance, MAX_STREAM_NAME_LEN,
39};
40
41#[cfg(test)]
42#[path = "unit_tests/runtime_tests.rs"]
43mod tests;
44
45pub trait WithContext {
46    type UserContext;
47    type Code;
48}
49
50impl WithContext for UserContractInstance {
51    type UserContext = Timestamp;
52    type Code = UserContractCode;
53}
54
55impl WithContext for UserServiceInstance {
56    type UserContext = ();
57    type Code = UserServiceCode;
58}
59
60#[cfg(test)]
61impl WithContext for Arc<dyn std::any::Any + Send + Sync> {
62    type UserContext = ();
63    type Code = ();
64}
65
66#[derive(Debug)]
67pub struct SyncRuntime<UserInstance: WithContext>(Option<SyncRuntimeHandle<UserInstance>>);
68
69pub type ContractSyncRuntime = SyncRuntime<UserContractInstance>;
70
71/// The synchronous runtime used to execute service queries.
72pub struct ServiceSyncRuntime {
73    runtime: SyncRuntime<UserServiceInstance>,
74    current_context: QueryContext,
75}
76
77#[derive(Debug)]
78pub struct SyncRuntimeHandle<UserInstance: WithContext>(
79    Arc<Mutex<SyncRuntimeInternal<UserInstance>>>,
80);
81
82/// A handle to the synchronous runtime used when executing contracts.
83pub type ContractSyncRuntimeHandle = SyncRuntimeHandle<UserContractInstance>;
84/// A handle to the synchronous runtime used when executing services.
85pub type ServiceSyncRuntimeHandle = SyncRuntimeHandle<UserServiceInstance>;
86
87/// Runtime data tracked during the execution of a transaction on the synchronous thread.
88#[derive(Debug)]
89pub struct SyncRuntimeInternal<UserInstance: WithContext> {
90    /// The current chain ID.
91    chain_id: ChainId,
92    /// The height of the next block that will be added to this chain. During operations
93    /// and messages, this is the current block height.
94    height: BlockHeight,
95    /// The current consensus round. Only available during block validation in multi-leader rounds.
96    round: Option<u32>,
97    /// The current message being executed, if there is one.
98    #[debug(skip_if = Option::is_none)]
99    executing_message: Option<ExecutingMessage>,
100
101    /// How to interact with the storage view of the execution state.
102    execution_state_sender: ExecutionStateSender,
103
104    /// If applications are being finalized.
105    ///
106    /// If [`true`], disables cross-application calls.
107    is_finalizing: bool,
108    /// Applications that need to be finalized.
109    applications_to_finalize: Vec<ApplicationId>,
110
111    /// Application instances loaded in this transaction.
112    preloaded_applications: HashMap<ApplicationId, (UserInstance::Code, ApplicationDescription)>,
113    /// Application instances loaded in this transaction.
114    loaded_applications: HashMap<ApplicationId, LoadedApplication<UserInstance>>,
115    /// The current stack of application descriptions.
116    call_stack: Vec<ApplicationStatus>,
117    /// The set of the IDs of the applications that are in the `call_stack`.
118    active_applications: HashSet<ApplicationId>,
119    /// The operations scheduled during this query.
120    scheduled_operations: Vec<Operation>,
121
122    /// Track application states based on views.
123    view_user_states: BTreeMap<ApplicationId, ViewUserState>,
124
125    /// The deadline this runtime should finish executing.
126    ///
127    /// Used to limit the execution time of services running as oracles.
128    deadline: Option<Instant>,
129
130    /// Where to send a refund for the unused part of the grant after execution, if any.
131    #[debug(skip_if = Option::is_none)]
132    refund_grant_to: Option<Account>,
133    /// Controller to track fuel and storage consumption.
134    resource_controller: ResourceController,
135    /// Additional context for the runtime.
136    user_context: UserInstance::UserContext,
137    /// Whether contract log messages should be output.
138    allow_application_logs: bool,
139}
140
141/// The runtime status of an application.
142#[derive(Debug)]
143struct ApplicationStatus {
144    /// The caller application ID, if forwarded during the call.
145    caller_id: Option<ApplicationId>,
146    /// The application ID.
147    id: ApplicationId,
148    /// The application description.
149    description: ApplicationDescription,
150    /// The authenticated signer for the execution thread, if any.
151    signer: Option<AccountOwner>,
152}
153
154/// A loaded application instance.
155#[derive(Debug)]
156struct LoadedApplication<Instance> {
157    instance: Arc<Mutex<Instance>>,
158    description: ApplicationDescription,
159}
160
161impl<Instance> LoadedApplication<Instance> {
162    /// Creates a new [`LoadedApplication`] entry from the `instance` and its `description`.
163    fn new(instance: Instance, description: ApplicationDescription) -> Self {
164        LoadedApplication {
165            instance: Arc::new(Mutex::new(instance)),
166            description,
167        }
168    }
169}
170
171impl<Instance> Clone for LoadedApplication<Instance> {
172    // Manual implementation is needed to prevent the derive macro from adding an `Instance: Clone`
173    // bound
174    fn clone(&self) -> Self {
175        LoadedApplication {
176            instance: self.instance.clone(),
177            description: self.description.clone(),
178        }
179    }
180}
181
182#[derive(Debug)]
183enum Promise<T> {
184    Ready(T),
185    Pending(Receiver<T>),
186}
187
188impl<T> Promise<T> {
189    fn force(&mut self) -> Result<(), ExecutionError> {
190        if let Promise::Pending(receiver) = self {
191            let value = receiver
192                .recv_ref()
193                .map_err(|oneshot::RecvError| ExecutionError::MissingRuntimeResponse)?;
194            *self = Promise::Ready(value);
195        }
196        Ok(())
197    }
198
199    fn read(self) -> Result<T, ExecutionError> {
200        match self {
201            Promise::Pending(receiver) => {
202                let value = receiver.recv_response()?;
203                Ok(value)
204            }
205            Promise::Ready(value) => Ok(value),
206        }
207    }
208}
209
210/// Manages a set of pending queries returning values of type `T`.
211#[derive(Debug, Default)]
212struct QueryManager<T> {
213    /// The queries in progress.
214    pending_queries: BTreeMap<u32, Promise<T>>,
215    /// The number of queries ever registered so far. Used for the index of the next query.
216    query_count: u32,
217    /// The number of active queries.
218    active_query_count: u32,
219}
220
221impl<T> QueryManager<T> {
222    fn register(&mut self, receiver: Receiver<T>) -> Result<u32, ExecutionError> {
223        let id = self.query_count;
224        self.pending_queries.insert(id, Promise::Pending(receiver));
225        self.query_count = self
226            .query_count
227            .checked_add(1)
228            .ok_or(ArithmeticError::Overflow)?;
229        self.active_query_count = self
230            .active_query_count
231            .checked_add(1)
232            .ok_or(ArithmeticError::Overflow)?;
233        Ok(id)
234    }
235
236    fn wait(&mut self, id: u32) -> Result<T, ExecutionError> {
237        let promise = self
238            .pending_queries
239            .remove(&id)
240            .ok_or(ExecutionError::InvalidPromise)?;
241        let value = promise.read()?;
242        self.active_query_count -= 1;
243        Ok(value)
244    }
245
246    fn force_all(&mut self) -> Result<(), ExecutionError> {
247        for promise in self.pending_queries.values_mut() {
248            promise.force()?;
249        }
250        Ok(())
251    }
252}
253
254type Keys = Vec<Vec<u8>>;
255type Value = Vec<u8>;
256type KeyValues = Vec<(Vec<u8>, Vec<u8>)>;
257
258#[derive(Debug, Default)]
259struct ViewUserState {
260    /// The contains-key queries in progress.
261    contains_key_queries: QueryManager<bool>,
262    /// The contains-keys queries in progress.
263    contains_keys_queries: QueryManager<Vec<bool>>,
264    /// The read-value queries in progress.
265    read_value_queries: QueryManager<Option<Value>>,
266    /// The read-multi-values queries in progress.
267    read_multi_values_queries: QueryManager<Vec<Option<Value>>>,
268    /// The find-keys queries in progress.
269    find_keys_queries: QueryManager<Keys>,
270    /// The find-key-values queries in progress.
271    find_key_values_queries: QueryManager<KeyValues>,
272}
273
274impl ViewUserState {
275    fn force_all_pending_queries(&mut self) -> Result<(), ExecutionError> {
276        self.contains_key_queries.force_all()?;
277        self.contains_keys_queries.force_all()?;
278        self.read_value_queries.force_all()?;
279        self.read_multi_values_queries.force_all()?;
280        self.find_keys_queries.force_all()?;
281        self.find_key_values_queries.force_all()?;
282        Ok(())
283    }
284}
285
286impl<UserInstance: WithContext> Deref for SyncRuntime<UserInstance> {
287    type Target = SyncRuntimeHandle<UserInstance>;
288
289    fn deref(&self) -> &Self::Target {
290        self.0.as_ref().expect(
291            "`SyncRuntime` should not be used after its `inner` contents have been moved out",
292        )
293    }
294}
295
296impl<UserInstance: WithContext> DerefMut for SyncRuntime<UserInstance> {
297    fn deref_mut(&mut self) -> &mut Self::Target {
298        self.0.as_mut().expect(
299            "`SyncRuntime` should not be used after its `inner` contents have been moved out",
300        )
301    }
302}
303
304impl<UserInstance: WithContext> Drop for SyncRuntime<UserInstance> {
305    fn drop(&mut self) {
306        // Ensure the `loaded_applications` are cleared to prevent circular references in
307        // the runtime
308        if let Some(handle) = self.0.take() {
309            handle.inner().loaded_applications.clear();
310        }
311    }
312}
313
314impl<UserInstance: WithContext> SyncRuntimeInternal<UserInstance> {
315    #[expect(clippy::too_many_arguments)]
316    fn new(
317        chain_id: ChainId,
318        height: BlockHeight,
319        round: Option<u32>,
320        executing_message: Option<ExecutingMessage>,
321        execution_state_sender: ExecutionStateSender,
322        deadline: Option<Instant>,
323        refund_grant_to: Option<Account>,
324        resource_controller: ResourceController,
325        user_context: UserInstance::UserContext,
326        allow_application_logs: bool,
327    ) -> Self {
328        Self {
329            chain_id,
330            height,
331            round,
332            executing_message,
333            execution_state_sender,
334            is_finalizing: false,
335            applications_to_finalize: Vec::new(),
336            preloaded_applications: HashMap::new(),
337            loaded_applications: HashMap::new(),
338            call_stack: Vec::new(),
339            active_applications: HashSet::new(),
340            view_user_states: BTreeMap::new(),
341            deadline,
342            refund_grant_to,
343            resource_controller,
344            scheduled_operations: Vec::new(),
345            user_context,
346            allow_application_logs,
347        }
348    }
349
350    /// Returns the [`ApplicationStatus`] of the current application.
351    ///
352    /// The current application is the last to be pushed to the `call_stack`.
353    ///
354    /// # Panics
355    ///
356    /// If the call stack is empty.
357    fn current_application(&self) -> &ApplicationStatus {
358        self.call_stack
359            .last()
360            .expect("Call stack is unexpectedly empty")
361    }
362
363    /// Inserts a new [`ApplicationStatus`] to the end of the `call_stack`.
364    ///
365    /// Ensures the application's ID is also tracked in the `active_applications` set.
366    fn push_application(&mut self, status: ApplicationStatus) {
367        self.active_applications.insert(status.id);
368        self.call_stack.push(status);
369    }
370
371    /// Removes the [`current_application`][`Self::current_application`] from the `call_stack`.
372    ///
373    /// Ensures the application's ID is also removed from the `active_applications` set.
374    ///
375    /// # Panics
376    ///
377    /// If the call stack is empty.
378    fn pop_application(&mut self) -> ApplicationStatus {
379        let status = self
380            .call_stack
381            .pop()
382            .expect("Can't remove application from empty call stack");
383        assert!(self.active_applications.remove(&status.id));
384        status
385    }
386
387    /// Ensures that a call to `application_id` is not-reentrant.
388    ///
389    /// Returns an error if there already is an entry for `application_id` in the call stack.
390    fn check_for_reentrancy(&self, application_id: ApplicationId) -> Result<(), ExecutionError> {
391        ensure!(
392            !self.active_applications.contains(&application_id),
393            ExecutionError::ReentrantCall(application_id)
394        );
395        Ok(())
396    }
397}
398
399impl SyncRuntimeInternal<UserContractInstance> {
400    /// Loads a contract instance, initializing it with this runtime if needed.
401    #[instrument(skip_all, fields(application_id = %id))]
402    fn load_contract_instance(
403        &mut self,
404        this: SyncRuntimeHandle<UserContractInstance>,
405        id: ApplicationId,
406    ) -> Result<LoadedApplication<UserContractInstance>, ExecutionError> {
407        match self.loaded_applications.entry(id) {
408            hash_map::Entry::Occupied(entry) => Ok(entry.get().clone()),
409
410            hash_map::Entry::Vacant(entry) => {
411                // First time actually using the application. Let's see if the code was
412                // pre-loaded.
413                let (code, description) = match self.preloaded_applications.entry(id) {
414                    // TODO(#2927): support dynamic loading of modules on the Web
415                    #[cfg(web)]
416                    hash_map::Entry::Vacant(_) => {
417                        drop(this);
418                        return Err(ExecutionError::UnsupportedDynamicApplicationLoad(Box::new(
419                            id,
420                        )));
421                    }
422                    #[cfg(not(web))]
423                    hash_map::Entry::Vacant(entry) => {
424                        let (code, description) = self
425                            .execution_state_sender
426                            .send_request(move |callback| ExecutionRequest::LoadContract {
427                                id,
428                                callback,
429                            })?
430                            .recv_response()?;
431                        entry.insert((code, description)).clone()
432                    }
433                    hash_map::Entry::Occupied(entry) => entry.get().clone(),
434                };
435                let instance = code.instantiate(this)?;
436
437                self.applications_to_finalize.push(id);
438                Ok(entry
439                    .insert(LoadedApplication::new(instance, description))
440                    .clone())
441            }
442        }
443    }
444
445    /// Configures the runtime for executing a call to a different contract.
446    fn prepare_for_call(
447        &mut self,
448        this: ContractSyncRuntimeHandle,
449        authenticated: bool,
450        callee_id: ApplicationId,
451    ) -> Result<Arc<Mutex<UserContractInstance>>, ExecutionError> {
452        self.check_for_reentrancy(callee_id)?;
453
454        ensure!(
455            !self.is_finalizing,
456            ExecutionError::CrossApplicationCallInFinalize {
457                caller_id: Box::new(self.current_application().id),
458                callee_id: Box::new(callee_id),
459            }
460        );
461
462        // Load the application.
463        let application = self.load_contract_instance(this, callee_id)?;
464
465        let caller = self.current_application();
466        let caller_id = caller.id;
467        let caller_signer = caller.signer;
468        // Make the call to user code.
469        let authenticated_signer = match caller_signer {
470            Some(signer) if authenticated => Some(signer),
471            _ => None,
472        };
473        let authenticated_caller_id = authenticated.then_some(caller_id);
474        self.push_application(ApplicationStatus {
475            caller_id: authenticated_caller_id,
476            id: callee_id,
477            description: application.description,
478            // Allow further nested calls to be authenticated if this one is.
479            signer: authenticated_signer,
480        });
481        Ok(application.instance)
482    }
483
484    /// Cleans up the runtime after the execution of a call to a different contract.
485    fn finish_call(&mut self) {
486        self.pop_application();
487    }
488
489    /// Runs the service in a separate thread as an oracle.
490    fn run_service_oracle_query(
491        &mut self,
492        application_id: ApplicationId,
493        query: Vec<u8>,
494    ) -> Result<Vec<u8>, ExecutionError> {
495        let timeout = self
496            .resource_controller
497            .remaining_service_oracle_execution_time()?;
498        let execution_start = Instant::now();
499        let deadline = Some(execution_start + timeout);
500        let response = self
501            .execution_state_sender
502            .send_request(|callback| ExecutionRequest::QueryServiceOracle {
503                deadline,
504                application_id,
505                next_block_height: self.height,
506                query,
507                callback,
508            })?
509            .recv_response()?;
510
511        self.resource_controller
512            .track_service_oracle_execution(execution_start.elapsed())?;
513        self.resource_controller
514            .track_service_oracle_response(response.len())?;
515
516        Ok(response)
517    }
518}
519
520impl SyncRuntimeInternal<UserServiceInstance> {
521    /// Initializes a service instance with this runtime.
522    fn load_service_instance(
523        &mut self,
524        this: SyncRuntimeHandle<UserServiceInstance>,
525        id: ApplicationId,
526    ) -> Result<LoadedApplication<UserServiceInstance>, ExecutionError> {
527        match self.loaded_applications.entry(id) {
528            hash_map::Entry::Occupied(entry) => Ok(entry.get().clone()),
529
530            hash_map::Entry::Vacant(entry) => {
531                // First time actually using the application. Let's see if the code was
532                // pre-loaded.
533                let (code, description) = match self.preloaded_applications.entry(id) {
534                    // TODO(#2927): support dynamic loading of modules on the Web
535                    #[cfg(web)]
536                    hash_map::Entry::Vacant(_) => {
537                        drop(this);
538                        return Err(ExecutionError::UnsupportedDynamicApplicationLoad(Box::new(
539                            id,
540                        )));
541                    }
542                    #[cfg(not(web))]
543                    hash_map::Entry::Vacant(entry) => {
544                        let (code, description) = self
545                            .execution_state_sender
546                            .send_request(move |callback| ExecutionRequest::LoadService {
547                                id,
548                                callback,
549                            })?
550                            .recv_response()?;
551                        entry.insert((code, description)).clone()
552                    }
553                    hash_map::Entry::Occupied(entry) => entry.get().clone(),
554                };
555                let instance = code.instantiate(this)?;
556
557                self.applications_to_finalize.push(id);
558                Ok(entry
559                    .insert(LoadedApplication::new(instance, description))
560                    .clone())
561            }
562        }
563    }
564}
565
566impl<UserInstance: WithContext> SyncRuntime<UserInstance> {
567    fn into_inner(mut self) -> Option<SyncRuntimeInternal<UserInstance>> {
568        let handle = self.0.take().expect(
569            "`SyncRuntime` should not be used after its `inner` contents have been moved out",
570        );
571        let runtime = Arc::into_inner(handle.0)?
572            .into_inner()
573            .expect("`SyncRuntime` should run in a single thread which should not panic");
574        Some(runtime)
575    }
576}
577
578impl<UserInstance: WithContext> From<SyncRuntimeInternal<UserInstance>>
579    for SyncRuntimeHandle<UserInstance>
580{
581    fn from(runtime: SyncRuntimeInternal<UserInstance>) -> Self {
582        SyncRuntimeHandle(Arc::new(Mutex::new(runtime)))
583    }
584}
585
586impl<UserInstance: WithContext> SyncRuntimeHandle<UserInstance> {
587    fn inner(&self) -> std::sync::MutexGuard<'_, SyncRuntimeInternal<UserInstance>> {
588        self.0
589            .try_lock()
590            .expect("Synchronous runtimes run on a single execution thread")
591    }
592}
593
594impl<UserInstance: WithContext> BaseRuntime for SyncRuntimeHandle<UserInstance>
595where
596    Self: ContractOrServiceRuntime,
597{
598    type Read = ();
599    type ReadValueBytes = u32;
600    type ContainsKey = u32;
601    type ContainsKeys = u32;
602    type ReadMultiValuesBytes = u32;
603    type FindKeysByPrefix = u32;
604    type FindKeyValuesByPrefix = u32;
605
606    fn chain_id(&mut self) -> Result<ChainId, ExecutionError> {
607        let mut this = self.inner();
608        let chain_id = this.chain_id;
609        this.resource_controller.track_runtime_chain_id()?;
610        Ok(chain_id)
611    }
612
613    fn block_height(&mut self) -> Result<BlockHeight, ExecutionError> {
614        let mut this = self.inner();
615        let height = this.height;
616        this.resource_controller.track_runtime_block_height()?;
617        Ok(height)
618    }
619
620    fn application_id(&mut self) -> Result<ApplicationId, ExecutionError> {
621        let mut this = self.inner();
622        let application_id = this.current_application().id;
623        this.resource_controller.track_runtime_application_id()?;
624        Ok(application_id)
625    }
626
627    fn application_creator_chain_id(&mut self) -> Result<ChainId, ExecutionError> {
628        let mut this = self.inner();
629        let application_creator_chain_id = this.current_application().description.creator_chain_id;
630        this.resource_controller.track_runtime_application_id()?;
631        Ok(application_creator_chain_id)
632    }
633
634    fn read_application_description(
635        &mut self,
636        application_id: ApplicationId,
637    ) -> Result<ApplicationDescription, ExecutionError> {
638        let mut this = self.inner();
639        let description = this
640            .execution_state_sender
641            .send_request(|callback| ExecutionRequest::ReadApplicationDescription {
642                application_id,
643                callback,
644            })?
645            .recv_response()?;
646        this.resource_controller
647            .track_runtime_application_description(&description)?;
648        Ok(description)
649    }
650
651    fn application_parameters(&mut self) -> Result<Vec<u8>, ExecutionError> {
652        let mut this = self.inner();
653        let parameters = this.current_application().description.parameters.clone();
654        this.resource_controller
655            .track_runtime_application_parameters(&parameters)?;
656        Ok(parameters)
657    }
658
659    fn read_system_timestamp(&mut self) -> Result<Timestamp, ExecutionError> {
660        let mut this = self.inner();
661        let timestamp = this
662            .execution_state_sender
663            .send_request(|callback| ExecutionRequest::SystemTimestamp { callback })?
664            .recv_response()?;
665        this.resource_controller.track_runtime_timestamp()?;
666        Ok(timestamp)
667    }
668
669    fn read_chain_balance(&mut self) -> Result<Amount, ExecutionError> {
670        let mut this = self.inner();
671        let balance = this
672            .execution_state_sender
673            .send_request(|callback| ExecutionRequest::ChainBalance { callback })?
674            .recv_response()?;
675        this.resource_controller.track_runtime_balance()?;
676        Ok(balance)
677    }
678
679    fn read_owner_balance(&mut self, owner: AccountOwner) -> Result<Amount, ExecutionError> {
680        let mut this = self.inner();
681        let balance = this
682            .execution_state_sender
683            .send_request(|callback| ExecutionRequest::OwnerBalance { owner, callback })?
684            .recv_response()?;
685        this.resource_controller.track_runtime_balance()?;
686        Ok(balance)
687    }
688
689    fn read_owner_balances(&mut self) -> Result<Vec<(AccountOwner, Amount)>, ExecutionError> {
690        let mut this = self.inner();
691        let owner_balances = this
692            .execution_state_sender
693            .send_request(|callback| ExecutionRequest::OwnerBalances { callback })?
694            .recv_response()?;
695        this.resource_controller
696            .track_runtime_owner_balances(&owner_balances)?;
697        Ok(owner_balances)
698    }
699
700    fn read_balance_owners(&mut self) -> Result<Vec<AccountOwner>, ExecutionError> {
701        let mut this = self.inner();
702        let owners = this
703            .execution_state_sender
704            .send_request(|callback| ExecutionRequest::BalanceOwners { callback })?
705            .recv_response()?;
706        this.resource_controller.track_runtime_owners(&owners)?;
707        Ok(owners)
708    }
709
710    fn chain_ownership(&mut self) -> Result<ChainOwnership, ExecutionError> {
711        let mut this = self.inner();
712        let chain_ownership = this
713            .execution_state_sender
714            .send_request(|callback| ExecutionRequest::ChainOwnership { callback })?
715            .recv_response()?;
716        this.resource_controller
717            .track_runtime_chain_ownership(&chain_ownership)?;
718        Ok(chain_ownership)
719    }
720
721    fn application_permissions(&mut self) -> Result<ApplicationPermissions, ExecutionError> {
722        let this = self.inner();
723        let application_permissions = this
724            .execution_state_sender
725            .send_request(|callback| ExecutionRequest::ApplicationPermissions { callback })?
726            .recv_response()?;
727        Ok(application_permissions)
728    }
729
730    fn contains_key_new(&mut self, key: Vec<u8>) -> Result<Self::ContainsKey, ExecutionError> {
731        let mut this = self.inner();
732        let id = this.current_application().id;
733        this.resource_controller.track_read_operation()?;
734        let receiver = this
735            .execution_state_sender
736            .send_request(move |callback| ExecutionRequest::ContainsKey { id, key, callback })?;
737        let state = this.view_user_states.entry(id).or_default();
738        state.contains_key_queries.register(receiver)
739    }
740
741    fn contains_key_wait(&mut self, promise: &Self::ContainsKey) -> Result<bool, ExecutionError> {
742        let mut this = self.inner();
743        let id = this.current_application().id;
744        let state = this.view_user_states.entry(id).or_default();
745        let value = state.contains_key_queries.wait(*promise)?;
746        Ok(value)
747    }
748
749    fn contains_keys_new(
750        &mut self,
751        keys: Vec<Vec<u8>>,
752    ) -> Result<Self::ContainsKeys, ExecutionError> {
753        let mut this = self.inner();
754        let id = this.current_application().id;
755        this.resource_controller.track_read_operation()?;
756        let receiver = this
757            .execution_state_sender
758            .send_request(move |callback| ExecutionRequest::ContainsKeys { id, keys, callback })?;
759        let state = this.view_user_states.entry(id).or_default();
760        state.contains_keys_queries.register(receiver)
761    }
762
763    fn contains_keys_wait(
764        &mut self,
765        promise: &Self::ContainsKeys,
766    ) -> Result<Vec<bool>, ExecutionError> {
767        let mut this = self.inner();
768        let id = this.current_application().id;
769        let state = this.view_user_states.entry(id).or_default();
770        let value = state.contains_keys_queries.wait(*promise)?;
771        Ok(value)
772    }
773
774    fn read_multi_values_bytes_new(
775        &mut self,
776        keys: Vec<Vec<u8>>,
777    ) -> Result<Self::ReadMultiValuesBytes, ExecutionError> {
778        let mut this = self.inner();
779        let id = this.current_application().id;
780        this.resource_controller.track_read_operation()?;
781        let receiver = this.execution_state_sender.send_request(move |callback| {
782            ExecutionRequest::ReadMultiValuesBytes { id, keys, callback }
783        })?;
784        let state = this.view_user_states.entry(id).or_default();
785        state.read_multi_values_queries.register(receiver)
786    }
787
788    fn read_multi_values_bytes_wait(
789        &mut self,
790        promise: &Self::ReadMultiValuesBytes,
791    ) -> Result<Vec<Option<Vec<u8>>>, ExecutionError> {
792        let mut this = self.inner();
793        let id = this.current_application().id;
794        let state = this.view_user_states.entry(id).or_default();
795        let values = state.read_multi_values_queries.wait(*promise)?;
796        for value in &values {
797            if let Some(value) = &value {
798                this.resource_controller
799                    .track_bytes_read(value.len() as u64)?;
800            }
801        }
802        Ok(values)
803    }
804
805    fn read_value_bytes_new(
806        &mut self,
807        key: Vec<u8>,
808    ) -> Result<Self::ReadValueBytes, ExecutionError> {
809        let mut this = self.inner();
810        let id = this.current_application().id;
811        this.resource_controller.track_read_operation()?;
812        let receiver = this
813            .execution_state_sender
814            .send_request(move |callback| ExecutionRequest::ReadValueBytes { id, key, callback })?;
815        let state = this.view_user_states.entry(id).or_default();
816        state.read_value_queries.register(receiver)
817    }
818
819    fn read_value_bytes_wait(
820        &mut self,
821        promise: &Self::ReadValueBytes,
822    ) -> Result<Option<Vec<u8>>, ExecutionError> {
823        let mut this = self.inner();
824        let id = this.current_application().id;
825        let value = {
826            let state = this.view_user_states.entry(id).or_default();
827            state.read_value_queries.wait(*promise)?
828        };
829        if let Some(value) = &value {
830            this.resource_controller
831                .track_bytes_read(value.len() as u64)?;
832        }
833        Ok(value)
834    }
835
836    fn find_keys_by_prefix_new(
837        &mut self,
838        key_prefix: Vec<u8>,
839    ) -> Result<Self::FindKeysByPrefix, ExecutionError> {
840        let mut this = self.inner();
841        let id = this.current_application().id;
842        this.resource_controller.track_read_operation()?;
843        let receiver = this.execution_state_sender.send_request(move |callback| {
844            ExecutionRequest::FindKeysByPrefix {
845                id,
846                key_prefix,
847                callback,
848            }
849        })?;
850        let state = this.view_user_states.entry(id).or_default();
851        state.find_keys_queries.register(receiver)
852    }
853
854    fn find_keys_by_prefix_wait(
855        &mut self,
856        promise: &Self::FindKeysByPrefix,
857    ) -> Result<Vec<Vec<u8>>, ExecutionError> {
858        let mut this = self.inner();
859        let id = this.current_application().id;
860        let keys = {
861            let state = this.view_user_states.entry(id).or_default();
862            state.find_keys_queries.wait(*promise)?
863        };
864        let mut read_size = 0;
865        for key in &keys {
866            read_size += key.len();
867        }
868        this.resource_controller
869            .track_bytes_read(read_size as u64)?;
870        Ok(keys)
871    }
872
873    fn find_key_values_by_prefix_new(
874        &mut self,
875        key_prefix: Vec<u8>,
876    ) -> Result<Self::FindKeyValuesByPrefix, ExecutionError> {
877        let mut this = self.inner();
878        let id = this.current_application().id;
879        this.resource_controller.track_read_operation()?;
880        let receiver = this.execution_state_sender.send_request(move |callback| {
881            ExecutionRequest::FindKeyValuesByPrefix {
882                id,
883                key_prefix,
884                callback,
885            }
886        })?;
887        let state = this.view_user_states.entry(id).or_default();
888        state.find_key_values_queries.register(receiver)
889    }
890
891    fn find_key_values_by_prefix_wait(
892        &mut self,
893        promise: &Self::FindKeyValuesByPrefix,
894    ) -> Result<Vec<(Vec<u8>, Vec<u8>)>, ExecutionError> {
895        let mut this = self.inner();
896        let id = this.current_application().id;
897        let state = this.view_user_states.entry(id).or_default();
898        let key_values = state.find_key_values_queries.wait(*promise)?;
899        let mut read_size = 0;
900        for (key, value) in &key_values {
901            read_size += key.len() + value.len();
902        }
903        this.resource_controller
904            .track_bytes_read(read_size as u64)?;
905        Ok(key_values)
906    }
907
908    fn perform_http_request(
909        &mut self,
910        request: http::Request,
911    ) -> Result<http::Response, ExecutionError> {
912        let mut this = self.inner();
913        let app_permissions = this
914            .execution_state_sender
915            .send_request(|callback| ExecutionRequest::GetApplicationPermissions { callback })?
916            .recv_response()?;
917
918        let app_id = this.current_application().id;
919        ensure!(
920            app_permissions.can_make_http_requests(&app_id),
921            ExecutionError::UnauthorizedApplication(app_id)
922        );
923
924        this.resource_controller.track_http_request()?;
925
926        let response = this
927            .execution_state_sender
928            .send_request(|callback| ExecutionRequest::PerformHttpRequest {
929                request,
930                http_responses_are_oracle_responses:
931                    Self::LIMIT_HTTP_RESPONSE_SIZE_TO_ORACLE_RESPONSE_SIZE,
932                callback,
933            })?
934            .recv_response()?;
935        Ok(response)
936    }
937
938    fn assert_before(&mut self, timestamp: Timestamp) -> Result<(), ExecutionError> {
939        let this = self.inner();
940        this.execution_state_sender
941            .send_request(|callback| ExecutionRequest::AssertBefore {
942                timestamp,
943                callback,
944            })?
945            .recv_response()?
946    }
947
948    fn read_data_blob(&mut self, hash: DataBlobHash) -> Result<Vec<u8>, ExecutionError> {
949        let this = self.inner();
950        let blob_id = hash.into();
951        let content = this
952            .execution_state_sender
953            .send_request(|callback| ExecutionRequest::ReadBlobContent { blob_id, callback })?
954            .recv_response()?;
955        Ok(content.into_vec_or_clone())
956    }
957
958    fn assert_data_blob_exists(&mut self, hash: DataBlobHash) -> Result<(), ExecutionError> {
959        let this = self.inner();
960        let blob_id = hash.into();
961        this.execution_state_sender
962            .send_request(|callback| ExecutionRequest::AssertBlobExists { blob_id, callback })?
963            .recv_response()?;
964        Ok(())
965    }
966
967    fn allow_application_logs(&mut self) -> Result<bool, ExecutionError> {
968        Ok(self.inner().allow_application_logs)
969    }
970
971    #[cfg(web)]
972    fn send_log(&mut self, message: String, level: tracing::log::Level) {
973        let this = self.inner();
974        // Fire-and-forget: ignore errors since logging shouldn't affect execution.
975        this.execution_state_sender
976            .unbounded_send(ExecutionRequest::Log { message, level })
977            .ok();
978    }
979}
980
981/// An extension trait to determine in compile time the different behaviors between contract and
982/// services in the implementation of [`BaseRuntime`].
983trait ContractOrServiceRuntime {
984    /// Configured to `true` if the HTTP response size should be limited to the oracle response
985    /// size.
986    ///
987    /// This is `false` for services, potentially allowing them to receive a larger HTTP response
988    /// and only storing in the block a shorter oracle response.
989    const LIMIT_HTTP_RESPONSE_SIZE_TO_ORACLE_RESPONSE_SIZE: bool;
990}
991
992impl ContractOrServiceRuntime for ContractSyncRuntimeHandle {
993    const LIMIT_HTTP_RESPONSE_SIZE_TO_ORACLE_RESPONSE_SIZE: bool = true;
994}
995
996impl ContractOrServiceRuntime for ServiceSyncRuntimeHandle {
997    const LIMIT_HTTP_RESPONSE_SIZE_TO_ORACLE_RESPONSE_SIZE: bool = false;
998}
999
1000impl<UserInstance: WithContext> Clone for SyncRuntimeHandle<UserInstance> {
1001    fn clone(&self) -> Self {
1002        SyncRuntimeHandle(self.0.clone())
1003    }
1004}
1005
1006impl ContractSyncRuntime {
1007    pub(crate) fn new(
1008        execution_state_sender: ExecutionStateSender,
1009        chain_id: ChainId,
1010        refund_grant_to: Option<Account>,
1011        resource_controller: ResourceController,
1012        action: &UserAction,
1013        allow_application_logs: bool,
1014    ) -> Self {
1015        SyncRuntime(Some(ContractSyncRuntimeHandle::from(
1016            SyncRuntimeInternal::new(
1017                chain_id,
1018                action.height(),
1019                action.round(),
1020                if let UserAction::Message(context, _) = action {
1021                    Some(context.into())
1022                } else {
1023                    None
1024                },
1025                execution_state_sender,
1026                None,
1027                refund_grant_to,
1028                resource_controller,
1029                action.timestamp(),
1030                allow_application_logs,
1031            ),
1032        )))
1033    }
1034
1035    /// Preloads the code of a contract into the runtime's memory.
1036    pub(crate) fn preload_contract(
1037        &self,
1038        id: ApplicationId,
1039        code: UserContractCode,
1040        description: ApplicationDescription,
1041    ) {
1042        let this = self
1043            .0
1044            .as_ref()
1045            .expect("contracts shouldn't be preloaded while the runtime is being dropped");
1046        let mut this_guard = this.inner();
1047
1048        if let hash_map::Entry::Vacant(entry) = this_guard.preloaded_applications.entry(id) {
1049            entry.insert((code, description));
1050        }
1051    }
1052
1053    /// Main entry point to start executing a user action.
1054    pub(crate) fn run_action(
1055        mut self,
1056        application_id: ApplicationId,
1057        chain_id: ChainId,
1058        action: UserAction,
1059    ) -> Result<(Option<Vec<u8>>, ResourceController), ExecutionError> {
1060        let result = self
1061            .deref_mut()
1062            .run_action(application_id, chain_id, action)?;
1063        let runtime = self
1064            .into_inner()
1065            .expect("Runtime clones should have been freed by now");
1066
1067        Ok((result, runtime.resource_controller))
1068    }
1069}
1070
1071impl ContractSyncRuntimeHandle {
1072    #[instrument(skip_all, fields(application_id = %application_id))]
1073    fn run_action(
1074        &self,
1075        application_id: ApplicationId,
1076        chain_id: ChainId,
1077        action: UserAction,
1078    ) -> Result<Option<Vec<u8>>, ExecutionError> {
1079        let finalize_context = FinalizeContext {
1080            authenticated_signer: action.signer(),
1081            chain_id,
1082            height: action.height(),
1083            round: action.round(),
1084        };
1085
1086        {
1087            let runtime = self.inner();
1088            assert_eq!(runtime.chain_id, chain_id);
1089            assert_eq!(runtime.height, action.height());
1090        }
1091
1092        let signer = action.signer();
1093        let closure = move |code: &mut UserContractInstance| match action {
1094            UserAction::Instantiate(_context, argument) => {
1095                code.instantiate(argument).map(|()| None)
1096            }
1097            UserAction::Operation(_context, operation) => {
1098                code.execute_operation(operation).map(Option::Some)
1099            }
1100            UserAction::Message(_context, message) => code.execute_message(message).map(|()| None),
1101            UserAction::ProcessStreams(_context, updates) => {
1102                code.process_streams(updates).map(|()| None)
1103            }
1104        };
1105
1106        let result = self.execute(application_id, signer, closure)?;
1107        self.finalize(finalize_context)?;
1108        Ok(result)
1109    }
1110
1111    /// Notifies all loaded applications that execution is finalizing.
1112    #[instrument(skip_all)]
1113    fn finalize(&self, context: FinalizeContext) -> Result<(), ExecutionError> {
1114        let applications = mem::take(&mut self.inner().applications_to_finalize)
1115            .into_iter()
1116            .rev();
1117
1118        self.inner().is_finalizing = true;
1119
1120        for application in applications {
1121            self.execute(application, context.authenticated_signer, |contract| {
1122                contract.finalize().map(|_| None)
1123            })?;
1124            self.inner().loaded_applications.remove(&application);
1125        }
1126
1127        Ok(())
1128    }
1129
1130    /// Executes a `closure` with the contract code for the `application_id`.
1131    #[instrument(skip_all, fields(application_id = %application_id))]
1132    fn execute(
1133        &self,
1134        application_id: ApplicationId,
1135        signer: Option<AccountOwner>,
1136        closure: impl FnOnce(&mut UserContractInstance) -> Result<Option<Vec<u8>>, ExecutionError>,
1137    ) -> Result<Option<Vec<u8>>, ExecutionError> {
1138        let contract = {
1139            let mut runtime = self.inner();
1140            let application = runtime.load_contract_instance(self.clone(), application_id)?;
1141
1142            let status = ApplicationStatus {
1143                caller_id: None,
1144                id: application_id,
1145                description: application.description.clone(),
1146                signer,
1147            };
1148
1149            runtime.push_application(status);
1150
1151            application
1152        };
1153
1154        let result = closure(
1155            &mut contract
1156                .instance
1157                .try_lock()
1158                .expect("Application should not be already executing"),
1159        )?;
1160
1161        let mut runtime = self.inner();
1162        let application_status = runtime.pop_application();
1163        assert_eq!(application_status.caller_id, None);
1164        assert_eq!(application_status.id, application_id);
1165        assert_eq!(application_status.description, contract.description);
1166        assert_eq!(application_status.signer, signer);
1167        assert!(runtime.call_stack.is_empty());
1168
1169        Ok(result)
1170    }
1171}
1172
1173impl ContractRuntime for ContractSyncRuntimeHandle {
1174    fn authenticated_signer(&mut self) -> Result<Option<AccountOwner>, ExecutionError> {
1175        let this = self.inner();
1176        Ok(this.current_application().signer)
1177    }
1178
1179    fn message_is_bouncing(&mut self) -> Result<Option<bool>, ExecutionError> {
1180        Ok(self
1181            .inner()
1182            .executing_message
1183            .map(|metadata| metadata.is_bouncing))
1184    }
1185
1186    fn message_origin_chain_id(&mut self) -> Result<Option<ChainId>, ExecutionError> {
1187        Ok(self
1188            .inner()
1189            .executing_message
1190            .map(|metadata| metadata.origin))
1191    }
1192
1193    fn authenticated_caller_id(&mut self) -> Result<Option<ApplicationId>, ExecutionError> {
1194        let this = self.inner();
1195        if this.call_stack.len() <= 1 {
1196            return Ok(None);
1197        }
1198        Ok(this.current_application().caller_id)
1199    }
1200
1201    fn maximum_fuel_per_block(&mut self, vm_runtime: VmRuntime) -> Result<u64, ExecutionError> {
1202        Ok(match vm_runtime {
1203            VmRuntime::Wasm => {
1204                self.inner()
1205                    .resource_controller
1206                    .policy()
1207                    .maximum_wasm_fuel_per_block
1208            }
1209            VmRuntime::Evm => {
1210                self.inner()
1211                    .resource_controller
1212                    .policy()
1213                    .maximum_evm_fuel_per_block
1214            }
1215        })
1216    }
1217
1218    fn remaining_fuel(&mut self, vm_runtime: VmRuntime) -> Result<u64, ExecutionError> {
1219        Ok(self.inner().resource_controller.remaining_fuel(vm_runtime))
1220    }
1221
1222    fn consume_fuel(&mut self, fuel: u64, vm_runtime: VmRuntime) -> Result<(), ExecutionError> {
1223        let mut this = self.inner();
1224        this.resource_controller.track_fuel(fuel, vm_runtime)
1225    }
1226
1227    fn send_message(&mut self, message: SendMessageRequest<Vec<u8>>) -> Result<(), ExecutionError> {
1228        let mut this = self.inner();
1229        let application = this.current_application();
1230        let application_id = application.id;
1231        let authenticated_signer = application.signer;
1232        let mut refund_grant_to = this.refund_grant_to;
1233
1234        let grant = this
1235            .resource_controller
1236            .policy()
1237            .total_price(&message.grant)?;
1238        if grant.is_zero() {
1239            refund_grant_to = None;
1240        } else {
1241            this.resource_controller.track_grant(grant)?;
1242        }
1243        let kind = if message.is_tracked {
1244            MessageKind::Tracked
1245        } else {
1246            MessageKind::Simple
1247        };
1248
1249        this.execution_state_sender
1250            .send_request(|callback| ExecutionRequest::AddOutgoingMessage {
1251                message: OutgoingMessage {
1252                    destination: message.destination,
1253                    authenticated_signer,
1254                    refund_grant_to,
1255                    grant,
1256                    kind,
1257                    message: Message::User {
1258                        application_id,
1259                        bytes: message.message,
1260                    },
1261                },
1262                callback,
1263            })?
1264            .recv_response()?;
1265
1266        Ok(())
1267    }
1268
1269    fn transfer(
1270        &mut self,
1271        source: AccountOwner,
1272        destination: Account,
1273        amount: Amount,
1274    ) -> Result<(), ExecutionError> {
1275        let this = self.inner();
1276        let current_application = this.current_application();
1277        let application_id = current_application.id;
1278        let signer = current_application.signer;
1279
1280        this.execution_state_sender
1281            .send_request(|callback| ExecutionRequest::Transfer {
1282                source,
1283                destination,
1284                amount,
1285                signer,
1286                application_id,
1287                callback,
1288            })?
1289            .recv_response()?;
1290        Ok(())
1291    }
1292
1293    fn claim(
1294        &mut self,
1295        source: Account,
1296        destination: Account,
1297        amount: Amount,
1298    ) -> Result<(), ExecutionError> {
1299        let this = self.inner();
1300        let current_application = this.current_application();
1301        let application_id = current_application.id;
1302        let signer = current_application.signer;
1303
1304        this.execution_state_sender
1305            .send_request(|callback| ExecutionRequest::Claim {
1306                source,
1307                destination,
1308                amount,
1309                signer,
1310                application_id,
1311                callback,
1312            })?
1313            .recv_response()?;
1314        Ok(())
1315    }
1316
1317    fn try_call_application(
1318        &mut self,
1319        authenticated: bool,
1320        callee_id: ApplicationId,
1321        argument: Vec<u8>,
1322    ) -> Result<Vec<u8>, ExecutionError> {
1323        let contract = self
1324            .inner()
1325            .prepare_for_call(self.clone(), authenticated, callee_id)?;
1326
1327        let value = contract
1328            .try_lock()
1329            .expect("Applications should not have reentrant calls")
1330            .execute_operation(argument)?;
1331
1332        self.inner().finish_call();
1333
1334        Ok(value)
1335    }
1336
1337    fn emit(&mut self, stream_name: StreamName, value: Vec<u8>) -> Result<u32, ExecutionError> {
1338        let mut this = self.inner();
1339        ensure!(
1340            stream_name.0.len() <= MAX_STREAM_NAME_LEN,
1341            ExecutionError::StreamNameTooLong
1342        );
1343        let application_id = GenericApplicationId::User(this.current_application().id);
1344        let stream_id = StreamId {
1345            stream_name,
1346            application_id,
1347        };
1348        let value_len = value.len() as u64;
1349        let index = this
1350            .execution_state_sender
1351            .send_request(|callback| ExecutionRequest::Emit {
1352                stream_id,
1353                value,
1354                callback,
1355            })?
1356            .recv_response()?;
1357        // TODO(#365): Consider separate event fee categories.
1358        this.resource_controller.track_bytes_written(value_len)?;
1359        Ok(index)
1360    }
1361
1362    fn read_event(
1363        &mut self,
1364        chain_id: ChainId,
1365        stream_name: StreamName,
1366        index: u32,
1367    ) -> Result<Vec<u8>, ExecutionError> {
1368        let mut this = self.inner();
1369        ensure!(
1370            stream_name.0.len() <= MAX_STREAM_NAME_LEN,
1371            ExecutionError::StreamNameTooLong
1372        );
1373        let application_id = GenericApplicationId::User(this.current_application().id);
1374        let stream_id = StreamId {
1375            stream_name,
1376            application_id,
1377        };
1378        let event_id = EventId {
1379            stream_id,
1380            index,
1381            chain_id,
1382        };
1383        let event = this
1384            .execution_state_sender
1385            .send_request(|callback| ExecutionRequest::ReadEvent { event_id, callback })?
1386            .recv_response()?;
1387        // TODO(#365): Consider separate event fee categories.
1388        this.resource_controller
1389            .track_bytes_read(event.len() as u64)?;
1390        Ok(event)
1391    }
1392
1393    fn subscribe_to_events(
1394        &mut self,
1395        chain_id: ChainId,
1396        application_id: ApplicationId,
1397        stream_name: StreamName,
1398    ) -> Result<(), ExecutionError> {
1399        let this = self.inner();
1400        ensure!(
1401            stream_name.0.len() <= MAX_STREAM_NAME_LEN,
1402            ExecutionError::StreamNameTooLong
1403        );
1404        let stream_id = StreamId {
1405            stream_name,
1406            application_id: application_id.into(),
1407        };
1408        let subscriber_app_id = this.current_application().id;
1409        this.execution_state_sender
1410            .send_request(|callback| ExecutionRequest::SubscribeToEvents {
1411                chain_id,
1412                stream_id,
1413                subscriber_app_id,
1414                callback,
1415            })?
1416            .recv_response()?;
1417        Ok(())
1418    }
1419
1420    fn unsubscribe_from_events(
1421        &mut self,
1422        chain_id: ChainId,
1423        application_id: ApplicationId,
1424        stream_name: StreamName,
1425    ) -> Result<(), ExecutionError> {
1426        let this = self.inner();
1427        ensure!(
1428            stream_name.0.len() <= MAX_STREAM_NAME_LEN,
1429            ExecutionError::StreamNameTooLong
1430        );
1431        let stream_id = StreamId {
1432            stream_name,
1433            application_id: application_id.into(),
1434        };
1435        let subscriber_app_id = this.current_application().id;
1436        this.execution_state_sender
1437            .send_request(|callback| ExecutionRequest::UnsubscribeFromEvents {
1438                chain_id,
1439                stream_id,
1440                subscriber_app_id,
1441                callback,
1442            })?
1443            .recv_response()?;
1444        Ok(())
1445    }
1446
1447    fn query_service(
1448        &mut self,
1449        application_id: ApplicationId,
1450        query: Vec<u8>,
1451    ) -> Result<Vec<u8>, ExecutionError> {
1452        let mut this = self.inner();
1453
1454        let app_permissions = this
1455            .execution_state_sender
1456            .send_request(|callback| ExecutionRequest::GetApplicationPermissions { callback })?
1457            .recv_response()?;
1458
1459        let app_id = this.current_application().id;
1460        ensure!(
1461            app_permissions.can_call_services(&app_id),
1462            ExecutionError::UnauthorizedApplication(app_id)
1463        );
1464
1465        this.resource_controller.track_service_oracle_call()?;
1466
1467        this.run_service_oracle_query(application_id, query)
1468    }
1469
1470    fn open_chain(
1471        &mut self,
1472        ownership: ChainOwnership,
1473        application_permissions: ApplicationPermissions,
1474        balance: Amount,
1475    ) -> Result<ChainId, ExecutionError> {
1476        let parent_id = self.inner().chain_id;
1477        let block_height = self.block_height()?;
1478
1479        let timestamp = self.inner().user_context;
1480
1481        let chain_id = self
1482            .inner()
1483            .execution_state_sender
1484            .send_request(|callback| ExecutionRequest::OpenChain {
1485                ownership,
1486                balance,
1487                parent_id,
1488                block_height,
1489                timestamp,
1490                application_permissions,
1491                callback,
1492            })?
1493            .recv_response()?;
1494
1495        Ok(chain_id)
1496    }
1497
1498    fn close_chain(&mut self) -> Result<(), ExecutionError> {
1499        let this = self.inner();
1500        let application_id = this.current_application().id;
1501        this.execution_state_sender
1502            .send_request(|callback| ExecutionRequest::CloseChain {
1503                application_id,
1504                callback,
1505            })?
1506            .recv_response()?
1507    }
1508
1509    fn change_ownership(&mut self, ownership: ChainOwnership) -> Result<(), ExecutionError> {
1510        let this = self.inner();
1511        let application_id = this.current_application().id;
1512        this.execution_state_sender
1513            .send_request(|callback| ExecutionRequest::ChangeOwnership {
1514                application_id,
1515                ownership,
1516                callback,
1517            })?
1518            .recv_response()?
1519    }
1520
1521    fn change_application_permissions(
1522        &mut self,
1523        application_permissions: ApplicationPermissions,
1524    ) -> Result<(), ExecutionError> {
1525        let this = self.inner();
1526        let application_id = this.current_application().id;
1527        this.execution_state_sender
1528            .send_request(|callback| ExecutionRequest::ChangeApplicationPermissions {
1529                application_id,
1530                application_permissions,
1531                callback,
1532            })?
1533            .recv_response()?
1534    }
1535
1536    fn create_application(
1537        &mut self,
1538        module_id: ModuleId,
1539        parameters: Vec<u8>,
1540        argument: Vec<u8>,
1541        required_application_ids: Vec<ApplicationId>,
1542    ) -> Result<ApplicationId, ExecutionError> {
1543        let chain_id = self.inner().chain_id;
1544        let block_height = self.block_height()?;
1545
1546        let CreateApplicationResult { app_id } = self
1547            .inner()
1548            .execution_state_sender
1549            .send_request(move |callback| ExecutionRequest::CreateApplication {
1550                chain_id,
1551                block_height,
1552                module_id,
1553                parameters,
1554                required_application_ids,
1555                callback,
1556            })?
1557            .recv_response()??;
1558
1559        let contract = self.inner().prepare_for_call(self.clone(), true, app_id)?;
1560
1561        contract
1562            .try_lock()
1563            .expect("Applications should not have reentrant calls")
1564            .instantiate(argument)?;
1565
1566        self.inner().finish_call();
1567
1568        Ok(app_id)
1569    }
1570
1571    fn create_data_blob(&mut self, bytes: Vec<u8>) -> Result<DataBlobHash, ExecutionError> {
1572        let blob = Blob::new_data(bytes);
1573        let blob_id = blob.id();
1574        let this = self.inner();
1575        this.execution_state_sender
1576            .send_request(|callback| ExecutionRequest::AddCreatedBlob { blob, callback })?
1577            .recv_response()?;
1578        Ok(DataBlobHash(blob_id.hash))
1579    }
1580
1581    fn publish_module(
1582        &mut self,
1583        contract: Bytecode,
1584        service: Bytecode,
1585        vm_runtime: VmRuntime,
1586    ) -> Result<ModuleId, ExecutionError> {
1587        let (blobs, module_id) =
1588            crate::runtime::create_bytecode_blobs_sync(&contract, &service, vm_runtime);
1589        let this = self.inner();
1590        for blob in blobs {
1591            this.execution_state_sender
1592                .send_request(|callback| ExecutionRequest::AddCreatedBlob { blob, callback })?
1593                .recv_response()?;
1594        }
1595        Ok(module_id)
1596    }
1597
1598    fn validation_round(&mut self) -> Result<Option<u32>, ExecutionError> {
1599        let this = self.inner();
1600        let round = this.round;
1601        this.execution_state_sender
1602            .send_request(|callback| ExecutionRequest::ValidationRound { round, callback })?
1603            .recv_response()
1604    }
1605
1606    fn write_batch(&mut self, batch: Batch) -> Result<(), ExecutionError> {
1607        let mut this = self.inner();
1608        let id = this.current_application().id;
1609        let state = this.view_user_states.entry(id).or_default();
1610        state.force_all_pending_queries()?;
1611        this.resource_controller.track_write_operations(
1612            batch
1613                .num_operations()
1614                .try_into()
1615                .map_err(|_| ExecutionError::from(ArithmeticError::Overflow))?,
1616        )?;
1617        this.resource_controller
1618            .track_bytes_written(batch.size() as u64)?;
1619        this.execution_state_sender
1620            .send_request(|callback| ExecutionRequest::WriteBatch {
1621                id,
1622                batch,
1623                callback,
1624            })?
1625            .recv_response()?;
1626        Ok(())
1627    }
1628}
1629
1630impl ServiceSyncRuntime {
1631    /// Creates a new [`ServiceSyncRuntime`] ready to execute using a provided [`QueryContext`].
1632    pub fn new(execution_state_sender: ExecutionStateSender, context: QueryContext) -> Self {
1633        Self::new_with_deadline(execution_state_sender, context, None)
1634    }
1635
1636    /// Creates a new [`ServiceSyncRuntime`] ready to execute using a provided [`QueryContext`].
1637    pub fn new_with_deadline(
1638        execution_state_sender: ExecutionStateSender,
1639        context: QueryContext,
1640        deadline: Option<Instant>,
1641    ) -> Self {
1642        // Query the allow_application_logs setting from the execution state.
1643        let allow_application_logs = execution_state_sender
1644            .send_request(|callback| ExecutionRequest::AllowApplicationLogs { callback })
1645            .ok()
1646            .and_then(|receiver| receiver.recv_response().ok())
1647            .unwrap_or(false);
1648
1649        let runtime = SyncRuntime(Some(
1650            SyncRuntimeInternal::new(
1651                context.chain_id,
1652                context.next_block_height,
1653                None,
1654                None,
1655                execution_state_sender,
1656                deadline,
1657                None,
1658                ResourceController::default(),
1659                (),
1660                allow_application_logs,
1661            )
1662            .into(),
1663        ));
1664
1665        ServiceSyncRuntime {
1666            runtime,
1667            current_context: context,
1668        }
1669    }
1670
1671    /// Preloads the code of a service into the runtime's memory.
1672    pub(crate) fn preload_service(
1673        &self,
1674        id: ApplicationId,
1675        code: UserServiceCode,
1676        description: ApplicationDescription,
1677    ) {
1678        let this = self
1679            .runtime
1680            .0
1681            .as_ref()
1682            .expect("services shouldn't be preloaded while the runtime is being dropped");
1683        let mut this_guard = this.inner();
1684
1685        if let hash_map::Entry::Vacant(entry) = this_guard.preloaded_applications.entry(id) {
1686            entry.insert((code, description));
1687        }
1688    }
1689
1690    /// Runs the service runtime actor, waiting for `incoming_requests` to respond to.
1691    pub fn run(&mut self, incoming_requests: &std::sync::mpsc::Receiver<ServiceRuntimeRequest>) {
1692        while let Ok(request) = incoming_requests.recv() {
1693            let ServiceRuntimeRequest::Query {
1694                application_id,
1695                context,
1696                query,
1697                callback,
1698            } = request;
1699
1700            let result = self
1701                .prepare_for_query(context)
1702                .and_then(|()| self.run_query(application_id, query));
1703
1704            if let Err(err) = callback.send(result) {
1705                tracing::debug!(%err, "Receiver for query result has been dropped");
1706            }
1707        }
1708    }
1709
1710    /// Prepares the runtime to query an application.
1711    pub(crate) fn prepare_for_query(
1712        &mut self,
1713        new_context: QueryContext,
1714    ) -> Result<(), ExecutionError> {
1715        let expected_context = QueryContext {
1716            local_time: new_context.local_time,
1717            ..self.current_context
1718        };
1719
1720        if new_context != expected_context {
1721            let execution_state_sender = self.handle_mut().inner().execution_state_sender.clone();
1722            *self = ServiceSyncRuntime::new(execution_state_sender, new_context);
1723        } else {
1724            self.handle_mut()
1725                .inner()
1726                .execution_state_sender
1727                .send_request(|callback| ExecutionRequest::SetLocalTime {
1728                    local_time: new_context.local_time,
1729                    callback,
1730                })?
1731                .recv_response()?;
1732        }
1733        Ok(())
1734    }
1735
1736    /// Queries an application specified by its [`ApplicationId`].
1737    pub(crate) fn run_query(
1738        &mut self,
1739        application_id: ApplicationId,
1740        query: Vec<u8>,
1741    ) -> Result<QueryOutcome<Vec<u8>>, ExecutionError> {
1742        let this = self.handle_mut();
1743        let response = this.try_query_application(application_id, query)?;
1744        let operations = mem::take(&mut this.inner().scheduled_operations);
1745
1746        Ok(QueryOutcome {
1747            response,
1748            operations,
1749        })
1750    }
1751
1752    /// Obtains the [`SyncRuntimeHandle`] stored in this [`ServiceSyncRuntime`].
1753    fn handle_mut(&mut self) -> &mut ServiceSyncRuntimeHandle {
1754        self.runtime.0.as_mut().expect(
1755            "`SyncRuntimeHandle` should be available while `SyncRuntime` hasn't been dropped",
1756        )
1757    }
1758}
1759
1760impl ServiceRuntime for ServiceSyncRuntimeHandle {
1761    /// Note that queries are not available from writable contexts.
1762    fn try_query_application(
1763        &mut self,
1764        queried_id: ApplicationId,
1765        argument: Vec<u8>,
1766    ) -> Result<Vec<u8>, ExecutionError> {
1767        let service = {
1768            let mut this = self.inner();
1769
1770            // Load the application.
1771            let application = this.load_service_instance(self.clone(), queried_id)?;
1772            // Make the call to user code.
1773            this.push_application(ApplicationStatus {
1774                caller_id: None,
1775                id: queried_id,
1776                description: application.description,
1777                signer: None,
1778            });
1779            application.instance
1780        };
1781        let response = service
1782            .try_lock()
1783            .expect("Applications should not have reentrant calls")
1784            .handle_query(argument)?;
1785        self.inner().pop_application();
1786        Ok(response)
1787    }
1788
1789    fn schedule_operation(&mut self, operation: Vec<u8>) -> Result<(), ExecutionError> {
1790        let mut this = self.inner();
1791        let application_id = this.current_application().id;
1792
1793        this.scheduled_operations.push(Operation::User {
1794            application_id,
1795            bytes: operation,
1796        });
1797
1798        Ok(())
1799    }
1800
1801    fn check_execution_time(&mut self) -> Result<(), ExecutionError> {
1802        if let Some(deadline) = self.inner().deadline {
1803            if Instant::now() >= deadline {
1804                return Err(ExecutionError::MaximumServiceOracleExecutionTimeExceeded);
1805            }
1806        }
1807        Ok(())
1808    }
1809}
1810
1811/// A request to the service runtime actor.
1812#[allow(missing_docs)]
1813pub enum ServiceRuntimeRequest {
1814    Query {
1815        application_id: ApplicationId,
1816        context: QueryContext,
1817        query: Vec<u8>,
1818        callback: oneshot::Sender<Result<QueryOutcome<Vec<u8>>, ExecutionError>>,
1819    },
1820}
1821
1822/// The origin of the execution.
1823#[derive(Clone, Copy, Debug)]
1824struct ExecutingMessage {
1825    is_bouncing: bool,
1826    origin: ChainId,
1827}
1828
1829impl From<&MessageContext> for ExecutingMessage {
1830    fn from(context: &MessageContext) -> Self {
1831        ExecutingMessage {
1832            is_bouncing: context.is_bouncing,
1833            origin: context.origin,
1834        }
1835    }
1836}
1837
1838/// Creates a compressed contract and service bytecode synchronously.
1839pub fn create_bytecode_blobs_sync(
1840    contract: &Bytecode,
1841    service: &Bytecode,
1842    vm_runtime: VmRuntime,
1843) -> (Vec<Blob>, ModuleId) {
1844    match vm_runtime {
1845        VmRuntime::Wasm => {
1846            let compressed_contract = contract.compress();
1847            let compressed_service = service.compress();
1848            let contract_blob = Blob::new_contract_bytecode(compressed_contract);
1849            let service_blob = Blob::new_service_bytecode(compressed_service);
1850            let module_id =
1851                ModuleId::new(contract_blob.id().hash, service_blob.id().hash, vm_runtime);
1852            (vec![contract_blob, service_blob], module_id)
1853        }
1854        VmRuntime::Evm => {
1855            let compressed_contract = contract.compress();
1856            let evm_contract_blob = Blob::new_evm_bytecode(compressed_contract);
1857            let module_id = ModuleId::new(
1858                evm_contract_blob.id().hash,
1859                evm_contract_blob.id().hash,
1860                vm_runtime,
1861            );
1862            (vec![evm_contract_blob], module_id)
1863        }
1864    }
1865}