1use 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
71pub 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
82pub type ContractSyncRuntimeHandle = SyncRuntimeHandle<UserContractInstance>;
84pub type ServiceSyncRuntimeHandle = SyncRuntimeHandle<UserServiceInstance>;
86
87#[derive(Debug)]
89pub struct SyncRuntimeInternal<UserInstance: WithContext> {
90 chain_id: ChainId,
92 height: BlockHeight,
95 round: Option<u32>,
97 #[debug(skip_if = Option::is_none)]
99 executing_message: Option<ExecutingMessage>,
100
101 execution_state_sender: ExecutionStateSender,
103
104 is_finalizing: bool,
108 applications_to_finalize: Vec<ApplicationId>,
110
111 preloaded_applications: HashMap<ApplicationId, (UserInstance::Code, ApplicationDescription)>,
113 loaded_applications: HashMap<ApplicationId, LoadedApplication<UserInstance>>,
115 call_stack: Vec<ApplicationStatus>,
117 active_applications: HashSet<ApplicationId>,
119 scheduled_operations: Vec<Operation>,
121
122 view_user_states: BTreeMap<ApplicationId, ViewUserState>,
124
125 deadline: Option<Instant>,
129
130 #[debug(skip_if = Option::is_none)]
132 refund_grant_to: Option<Account>,
133 resource_controller: ResourceController,
135 user_context: UserInstance::UserContext,
137 allow_application_logs: bool,
139}
140
141#[derive(Debug)]
143struct ApplicationStatus {
144 caller_id: Option<ApplicationId>,
146 id: ApplicationId,
148 description: ApplicationDescription,
150 signer: Option<AccountOwner>,
152}
153
154#[derive(Debug)]
156struct LoadedApplication<Instance> {
157 instance: Arc<Mutex<Instance>>,
158 description: ApplicationDescription,
159}
160
161impl<Instance> LoadedApplication<Instance> {
162 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 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#[derive(Debug, Default)]
212struct QueryManager<T> {
213 pending_queries: BTreeMap<u32, Promise<T>>,
215 query_count: u32,
217 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 contains_key_queries: QueryManager<bool>,
262 contains_keys_queries: QueryManager<Vec<bool>>,
264 read_value_queries: QueryManager<Option<Value>>,
266 read_multi_values_queries: QueryManager<Vec<Option<Value>>>,
268 find_keys_queries: QueryManager<Keys>,
270 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 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 fn current_application(&self) -> &ApplicationStatus {
358 self.call_stack
359 .last()
360 .expect("Call stack is unexpectedly empty")
361 }
362
363 fn push_application(&mut self, status: ApplicationStatus) {
367 self.active_applications.insert(status.id);
368 self.call_stack.push(status);
369 }
370
371 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 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 #[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 let (code, description) = match self.preloaded_applications.entry(id) {
414 #[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 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 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 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 signer: authenticated_signer,
480 });
481 Ok(application.instance)
482 }
483
484 fn finish_call(&mut self) {
486 self.pop_application();
487 }
488
489 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 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 let (code, description) = match self.preloaded_applications.entry(id) {
534 #[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(¶meters)?;
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 this.execution_state_sender
976 .unbounded_send(ExecutionRequest::Log { message, level })
977 .ok();
978 }
979}
980
981trait ContractOrServiceRuntime {
984 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 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 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 #[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 #[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 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 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 pub fn new(execution_state_sender: ExecutionStateSender, context: QueryContext) -> Self {
1633 Self::new_with_deadline(execution_state_sender, context, None)
1634 }
1635
1636 pub fn new_with_deadline(
1638 execution_state_sender: ExecutionStateSender,
1639 context: QueryContext,
1640 deadline: Option<Instant>,
1641 ) -> Self {
1642 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 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 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 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 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 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 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 let application = this.load_service_instance(self.clone(), queried_id)?;
1772 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#[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#[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
1838pub 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}