1use crate::accumulators::funds_read::AccountFundsRead;
5use crate::authority::AuthorityStore;
6use crate::authority::authority_per_epoch_store::AuthorityPerEpochStore;
7use crate::authority::authority_store::ExecutionLockWriteGuard;
8#[cfg(test)]
9use crate::authority::authority_store::SuiLockResult;
10use crate::authority::backpressure::BackpressureManager;
11use crate::authority::epoch_start_configuration::EpochFlag;
12use crate::authority::epoch_start_configuration::EpochStartConfiguration;
13use crate::global_state_hasher::GlobalStateHashStore;
14use crate::transaction_outputs::TransactionOutputs;
15use either::Either;
16use itertools::Itertools;
17use mysten_common::ZipDebugEqIteratorExt;
18use sui_types::accumulator_event::AccumulatorEvent;
19use sui_types::bridge::Bridge;
20
21use futures::{FutureExt, future::BoxFuture};
22use prometheus::Registry;
23use std::collections::HashSet;
24use std::path::Path;
25use std::sync::Arc;
26use sui_config::ExecutionCacheConfig;
27use sui_protocol_config::ProtocolVersion;
28use sui_types::base_types::{FullObjectID, VerifiedExecutionData};
29use sui_types::digests::{TransactionDigest, TransactionEffectsDigest};
30use sui_types::effects::{TransactionEffects, TransactionEvents};
31use sui_types::error::{SuiError, SuiErrorKind, SuiResult, UserInputError};
32use sui_types::executable_transaction::VerifiedExecutableTransaction;
33use sui_types::messages_checkpoint::CheckpointSequenceNumber;
34use sui_types::object::Object;
35use sui_types::storage::{
36 BackingPackageStore, BackingStore, FullObjectKey, MarkerValue, ObjectKey, ObjectOrTombstone,
37 ObjectStore, PackageObject, ParentSync, RuntimeObjectResolver,
38};
39use sui_types::sui_system_state::SuiSystemState;
40use sui_types::transaction::VerifiedTransaction;
41use sui_types::{
42 base_types::{EpochId, ObjectID, ObjectRef, SequenceNumber},
43 object::Owner,
44 storage::InputKey,
45};
46use typed_store::rocks::DBBatch;
47
48pub(crate) mod cache_types;
49pub mod metrics;
50mod object_locks;
51pub mod writeback_cache;
52
53pub use writeback_cache::WritebackCache;
54
55use metrics::ExecutionCacheMetrics;
56
57#[derive(Clone)]
62pub struct ExecutionCacheTraitPointers {
63 pub object_cache_reader: Arc<dyn ObjectCacheRead>,
64 pub transaction_cache_reader: Arc<dyn TransactionCacheRead>,
65 pub cache_writer: Arc<dyn ExecutionCacheWrite>,
66 pub backing_store: Arc<dyn BackingStore + Send + Sync>,
67 pub runtime_object_resolver: Arc<dyn RuntimeObjectResolver + Send + Sync>,
68 pub backing_package_store: Arc<dyn BackingPackageStore + Send + Sync>,
69 pub object_store: Arc<dyn ObjectStore + Send + Sync>,
70 pub reconfig_api: Arc<dyn ExecutionCacheReconfigAPI>,
71 pub global_state_hash_store: Arc<dyn GlobalStateHashStore>,
72 pub checkpoint_cache: Arc<dyn CheckpointCache>,
73 pub state_sync_store: Arc<dyn StateSyncAPI>,
74 pub cache_commit: Arc<dyn ExecutionCacheCommit>,
75 pub testing_api: Arc<dyn TestingAPI>,
76 pub account_funds_read: Arc<dyn AccountFundsRead>,
77}
78
79impl ExecutionCacheTraitPointers {
80 pub fn new<T>(cache: Arc<T>) -> Self
81 where
82 T: ObjectCacheRead
83 + TransactionCacheRead
84 + ExecutionCacheWrite
85 + BackingStore
86 + BackingPackageStore
87 + ObjectStore
88 + ExecutionCacheReconfigAPI
89 + GlobalStateHashStore
90 + CheckpointCache
91 + StateSyncAPI
92 + ExecutionCacheCommit
93 + TestingAPI
94 + AccountFundsRead
95 + 'static,
96 {
97 Self {
98 object_cache_reader: cache.clone(),
99 transaction_cache_reader: cache.clone(),
100 cache_writer: cache.clone(),
101 backing_store: cache.clone(),
102 runtime_object_resolver: cache.clone(),
103 backing_package_store: cache.clone(),
104 object_store: cache.clone(),
105 reconfig_api: cache.clone(),
106 global_state_hash_store: cache.clone(),
107 checkpoint_cache: cache.clone(),
108 state_sync_store: cache.clone(),
109 cache_commit: cache.clone(),
110 testing_api: cache.clone(),
111 account_funds_read: cache.clone(),
112 }
113 }
114}
115
116pub fn build_execution_cache(
117 cache_config: &ExecutionCacheConfig,
118 prometheus_registry: &Registry,
119 store: &Arc<AuthorityStore>,
120 backpressure_manager: Arc<BackpressureManager>,
121) -> ExecutionCacheTraitPointers {
122 let execution_cache_metrics = Arc::new(ExecutionCacheMetrics::new(prometheus_registry));
123
124 ExecutionCacheTraitPointers::new(
125 WritebackCache::new(
126 cache_config,
127 store.clone(),
128 execution_cache_metrics,
129 backpressure_manager,
130 )
131 .into(),
132 )
133}
134
135pub fn build_execution_cache_from_env(
138 prometheus_registry: &Registry,
139 store: &Arc<AuthorityStore>,
140) -> ExecutionCacheTraitPointers {
141 let execution_cache_metrics = Arc::new(ExecutionCacheMetrics::new(prometheus_registry));
142
143 ExecutionCacheTraitPointers::new(
144 WritebackCache::new(
145 &Default::default(),
146 store.clone(),
147 execution_cache_metrics,
148 BackpressureManager::new_for_tests(),
149 )
150 .into(),
151 )
152}
153
154pub type Batch = (Vec<Arc<TransactionOutputs>>, DBBatch);
155
156pub trait ExecutionCacheCommit: Send + Sync {
157 fn build_db_batch(&self, epoch: EpochId, digests: &[TransactionDigest]) -> Batch;
159
160 fn set_highest_committed_checkpoint_in_batch(
167 &self,
168 batch: &mut Batch,
169 checkpoint: CheckpointSequenceNumber,
170 );
171
172 fn commit_transaction_outputs(
176 &self,
177 epoch: EpochId,
178 batch: Batch,
179 digests: &[TransactionDigest],
180 );
181
182 fn persist_transaction(&self, transaction: &VerifiedExecutableTransaction);
186
187 fn approximate_pending_transaction_count(&self) -> u64;
189}
190
191pub trait ObjectCacheRead: Send + Sync {
192 fn get_package_object(&self, id: &ObjectID) -> SuiResult<Option<PackageObject>>;
193 fn force_reload_system_packages(&self, system_package_ids: &[ObjectID]);
194
195 fn get_object(&self, id: &ObjectID) -> Option<Object>;
196
197 fn get_objects(&self, objects: &[ObjectID]) -> Vec<Option<Object>> {
198 let mut ret = Vec::with_capacity(objects.len());
199 for object_id in objects {
200 ret.push(self.get_object(object_id));
201 }
202 ret
203 }
204
205 fn get_latest_object_ref_or_tombstone(&self, object_id: ObjectID) -> Option<ObjectRef>;
206
207 fn get_latest_object_or_tombstone(
208 &self,
209 object_id: ObjectID,
210 ) -> Option<(ObjectKey, ObjectOrTombstone)>;
211
212 fn get_object_by_key(&self, object_id: &ObjectID, version: SequenceNumber) -> Option<Object>;
213
214 fn multi_get_objects_by_key(&self, object_keys: &[ObjectKey]) -> Vec<Option<Object>>;
215
216 fn object_exists_by_key(&self, object_id: &ObjectID, version: SequenceNumber) -> bool;
217
218 fn multi_object_exists_by_key(&self, object_keys: &[ObjectKey]) -> Vec<bool>;
219
220 fn multi_get_objects_with_more_accurate_error_return(
228 &self,
229 object_refs: &[ObjectRef],
230 ) -> Result<Vec<Object>, SuiError> {
231 let objects = self
232 .multi_get_objects_by_key(&object_refs.iter().map(ObjectKey::from).collect::<Vec<_>>());
233 let mut result = Vec::new();
234 for (object_opt, object_ref) in objects.into_iter().zip_debug_eq(object_refs) {
235 match object_opt {
236 None => {
237 let live_objref = self._get_live_objref(object_ref.0)?;
238 let error = if live_objref.1 >= object_ref.1 {
239 UserInputError::ObjectVersionUnavailableForConsumption {
240 provided_obj_ref: *object_ref,
241 current_version: live_objref.1,
242 }
243 } else {
244 UserInputError::ObjectNotFound {
245 object_id: object_ref.0,
246 version: Some(object_ref.1),
247 }
248 };
249 return Err(SuiErrorKind::UserInputError { error }.into());
250 }
251 Some(object) => {
252 result.push(object);
253 }
254 }
255 }
256 assert_eq!(result.len(), object_refs.len());
257 Ok(result)
258 }
259
260 fn multi_input_objects_available(
264 &self,
265 keys: &[InputKey],
266 receiving_objects: &HashSet<InputKey>,
267 epoch: EpochId,
268 ) -> Vec<bool> {
269 let mut results = vec![false; keys.len()];
270 let non_canceled_keys = keys.iter().enumerate().filter(|(idx, key)| {
271 if key.is_cancelled() {
272 results[*idx] = true;
274 false
275 } else {
276 true
277 }
278 });
279 let (move_object_keys, package_object_keys): (Vec<_>, Vec<_>) = non_canceled_keys
280 .partition_map(|(idx, key)| match key {
281 InputKey::VersionedObject { id, version } => Either::Left((idx, (id, version))),
282 InputKey::Package { id } => Either::Right((idx, id)),
283 });
284
285 for ((idx, (id, version)), has_key) in move_object_keys.iter().zip_debug_eq(
286 self.multi_object_exists_by_key(
287 &move_object_keys
288 .iter()
289 .map(|(_, k)| ObjectKey(k.0.id(), *k.1))
290 .collect::<Vec<_>>(),
291 ),
292 ) {
293 if has_key {
295 results[*idx] = true;
296 } else if receiving_objects.contains(&InputKey::VersionedObject {
297 id: **id,
298 version: **version,
299 }) {
300 let is_available = self
307 .get_object(&id.id())
308 .map(|obj| obj.version() >= **version)
309 .unwrap_or(false)
310 || self.fastpath_stream_ended_at_version_or_after(id.id(), **version, epoch);
311 results[*idx] = is_available;
312 } else {
313 let is_consensus_stream_ended = self
316 .get_consensus_stream_end_tx_digest(FullObjectKey::new(**id, **version), epoch)
317 .is_some();
318 results[*idx] = is_consensus_stream_ended;
319 }
320 }
321
322 package_object_keys.into_iter().for_each(|(idx, id)| {
323 results[idx] = self.get_package_object(id).is_ok_and(|p| p.is_some());
326 });
327
328 results
329 }
330
331 fn multi_input_objects_available_cache_only(&self, keys: &[InputKey]) -> Vec<bool>;
332
333 fn find_object_lt_or_eq_version(
338 &self,
339 object_id: ObjectID,
340 version: SequenceNumber,
341 ) -> Option<Object>;
342
343 #[cfg(test)]
345 fn get_lock(&self, obj_ref: ObjectRef, epoch_store: &AuthorityPerEpochStore) -> SuiLockResult;
346
347 fn _get_live_objref(&self, object_id: ObjectID) -> SuiResult<ObjectRef>;
349
350 fn get_sui_system_state_object_unsafe(&self) -> SuiResult<SuiSystemState>;
351
352 fn get_bridge_object_unsafe(&self) -> SuiResult<Bridge>;
353
354 fn get_marker_value(&self, object_key: FullObjectKey, epoch_id: EpochId)
358 -> Option<MarkerValue>;
359
360 fn get_latest_marker(
362 &self,
363 object_id: FullObjectID,
364 epoch_id: EpochId,
365 ) -> Option<(SequenceNumber, MarkerValue)>;
366
367 fn get_last_consensus_stream_end_info(
370 &self,
371 object_id: FullObjectID,
372 epoch_id: EpochId,
373 ) -> Option<(SequenceNumber, TransactionDigest)> {
374 match self.get_latest_marker(object_id, epoch_id) {
375 Some((version, MarkerValue::ConsensusStreamEnded(digest))) => Some((version, digest)),
376 _ => None,
377 }
378 }
379
380 fn get_consensus_stream_end_tx_digest(
383 &self,
384 object_key: FullObjectKey,
385 epoch_id: EpochId,
386 ) -> Option<TransactionDigest> {
387 match self.get_marker_value(object_key, epoch_id) {
388 Some(MarkerValue::ConsensusStreamEnded(digest)) => Some(digest),
389 _ => None,
390 }
391 }
392
393 fn have_received_object_at_version(
394 &self,
395 object_key: FullObjectKey,
396 epoch_id: EpochId,
397 ) -> bool {
398 matches!(
399 self.get_marker_value(object_key, epoch_id),
400 Some(MarkerValue::Received)
401 )
402 }
403
404 fn fastpath_stream_ended_at_version_or_after(
405 &self,
406 object_id: ObjectID,
407 version: SequenceNumber,
408 epoch_id: EpochId,
409 ) -> bool {
410 let full_id = FullObjectID::Fastpath(object_id); matches!(
412 self.get_latest_marker(full_id, epoch_id),
413 Some((marker_version, MarkerValue::FastpathStreamEnded)) if marker_version >= version
414 )
415 }
416
417 fn get_highest_pruned_checkpoint(&self) -> Option<CheckpointSequenceNumber>;
419
420 fn notify_read_input_objects<'a>(
428 &'a self,
429 input_and_receiving_keys: &'a [InputKey],
430 receiving_keys: &'a HashSet<InputKey>,
431 epoch: EpochId,
432 ) -> BoxFuture<'a, ()>;
433}
434
435pub trait TransactionCacheRead: Send + Sync {
436 fn multi_get_transaction_blocks(
437 &self,
438 digests: &[TransactionDigest],
439 ) -> Vec<Option<Arc<VerifiedTransaction>>>;
440
441 fn get_transaction_block(
442 &self,
443 digest: &TransactionDigest,
444 ) -> Option<Arc<VerifiedTransaction>> {
445 self.multi_get_transaction_blocks(&[*digest])
446 .pop()
447 .expect("multi-get must return correct number of items")
448 }
449
450 fn multi_get_executed_effects_digests(
451 &self,
452 digests: &[TransactionDigest],
453 ) -> Vec<Option<TransactionEffectsDigest>>;
454
455 fn is_tx_already_executed(&self, digest: &TransactionDigest) -> bool {
456 self.multi_get_executed_effects_digests(&[*digest])
457 .pop()
458 .expect("multi-get must return correct number of items")
459 .is_some()
460 }
461
462 fn multi_get_executed_effects(
463 &self,
464 digests: &[TransactionDigest],
465 ) -> Vec<Option<TransactionEffects>> {
466 let effects_digests = self.multi_get_executed_effects_digests(digests);
467 assert_eq!(effects_digests.len(), digests.len());
468
469 let mut results = vec![None; digests.len()];
470 let mut fetch_digests = Vec::with_capacity(digests.len());
471 let mut fetch_indices = Vec::with_capacity(digests.len());
472
473 for (i, digest) in effects_digests.into_iter().enumerate() {
474 if let Some(digest) = digest {
475 fetch_digests.push(digest);
476 fetch_indices.push(i);
477 }
478 }
479
480 let effects = self.multi_get_effects(&fetch_digests);
481 for (i, effects) in fetch_indices.into_iter().zip_debug_eq(effects) {
482 results[i] = effects;
483 }
484
485 results
486 }
487
488 fn get_executed_effects(&self, digest: &TransactionDigest) -> Option<TransactionEffects> {
489 self.multi_get_executed_effects(&[*digest])
490 .pop()
491 .expect("multi-get must return correct number of items")
492 }
493
494 fn transaction_executed_in_last_epoch(
495 &self,
496 digest: &TransactionDigest,
497 current_epoch: EpochId,
498 ) -> bool;
499
500 fn multi_get_effects(
501 &self,
502 digests: &[TransactionEffectsDigest],
503 ) -> Vec<Option<TransactionEffects>>;
504
505 fn get_effects(&self, digest: &TransactionEffectsDigest) -> Option<TransactionEffects> {
506 self.multi_get_effects(&[*digest])
507 .pop()
508 .expect("multi-get must return correct number of items")
509 }
510
511 fn multi_get_events(&self, digests: &[TransactionDigest]) -> Vec<Option<TransactionEvents>>;
512
513 fn get_events(&self, digest: &TransactionDigest) -> Option<TransactionEvents> {
514 self.multi_get_events(&[*digest])
515 .pop()
516 .expect("multi-get must return correct number of items")
517 }
518
519 fn get_unchanged_loaded_runtime_objects(
520 &self,
521 digest: &TransactionDigest,
522 ) -> Option<Vec<ObjectKey>>;
523
524 fn multi_get_unchanged_loaded_runtime_objects(
525 &self,
526 digests: &[TransactionDigest],
527 ) -> Vec<Option<Vec<ObjectKey>>> {
528 digests
529 .iter()
530 .map(|digest| self.get_unchanged_loaded_runtime_objects(digest))
531 .collect()
532 }
533
534 fn take_accumulator_events(&self, digest: &TransactionDigest) -> Option<Vec<AccumulatorEvent>>;
535
536 fn notify_read_executed_effects_digests<'a>(
537 &'a self,
538 task_name: &'static str,
539 digests: &'a [TransactionDigest],
540 ) -> BoxFuture<'a, Vec<TransactionEffectsDigest>>;
541
542 fn notify_read_executed_effects<'a>(
555 &'a self,
556 task_name: &'static str,
557 digests: &'a [TransactionDigest],
558 ) -> BoxFuture<'a, Vec<TransactionEffects>> {
559 async move {
560 self.notify_read_executed_effects_may_fail(task_name, digests)
561 .await
562 .unwrap_or_else(|e| panic!("effects must exist: {e}"))
563 }
564 .boxed()
565 }
566
567 fn notify_read_executed_effects_may_fail<'a>(
572 &'a self,
573 task_name: &'static str,
574 digests: &'a [TransactionDigest],
575 ) -> BoxFuture<'a, SuiResult<Vec<TransactionEffects>>> {
576 async move {
577 let effects_digests = self
578 .notify_read_executed_effects_digests(task_name, digests)
579 .await;
580 self.multi_get_effects(&effects_digests)
581 .into_iter()
582 .zip_debug_eq(digests)
583 .map(|(e, digest)| {
584 e.ok_or_else(|| {
585 SuiError::from(SuiErrorKind::TransactionEffectsNotFound { digest: *digest })
586 })
587 })
588 .collect()
589 }
590 .boxed()
591 }
592}
593
594pub trait ExecutionCacheWrite: Send + Sync {
595 fn write_transaction_outputs(&self, epoch_id: EpochId, tx_outputs: Arc<TransactionOutputs>);
613
614 fn validate_owned_object_versions(&self, owned_input_objects: &[ObjectRef]) -> SuiResult;
617
618 #[cfg(test)]
622 fn write_object_entry_for_test(&self, object: Object);
623}
624
625pub trait CheckpointCache: Send + Sync {
626 fn deprecated_get_transaction_checkpoint(
631 &self,
632 digest: &TransactionDigest,
633 ) -> Option<(EpochId, CheckpointSequenceNumber)>;
634
635 fn deprecated_multi_get_transaction_checkpoint(
636 &self,
637 digests: &[TransactionDigest],
638 ) -> Vec<Option<(EpochId, CheckpointSequenceNumber)>>;
639
640 fn deprecated_insert_finalized_transactions(
641 &self,
642 digests: &[TransactionDigest],
643 epoch: EpochId,
644 sequence: CheckpointSequenceNumber,
645 );
646}
647
648pub trait ExecutionCacheReconfigAPI: Send + Sync {
649 fn insert_genesis_object(&self, object: Object);
650 fn bulk_insert_genesis_objects(&self, objects: &[Object]);
651
652 fn set_epoch_start_configuration(&self, epoch_start_config: &EpochStartConfiguration);
653
654 fn update_epoch_flags_metrics(&self, old: &[EpochFlag], new: &[EpochFlag]);
655
656 fn clear_state_end_of_epoch(&self, execution_guard: &ExecutionLockWriteGuard<'_>);
657
658 fn expensive_check_sui_conservation(
659 &self,
660 old_epoch_store: &AuthorityPerEpochStore,
661 ) -> SuiResult;
662
663 fn checkpoint_db(&self, path: &Path) -> SuiResult;
664
665 fn maybe_reaccumulate_state_hash(
668 &self,
669 cur_epoch_store: &AuthorityPerEpochStore,
670 new_protocol_version: ProtocolVersion,
671 );
672
673 fn reconfigure_cache<'a>(
677 &'a self,
678 epoch_start_config: &'a EpochStartConfiguration,
679 ) -> BoxFuture<'a, ()>;
680}
681
682pub trait StateSyncAPI: Send + Sync {
686 fn insert_transaction_and_effects(
687 &self,
688 transaction: &VerifiedTransaction,
689 transaction_effects: &TransactionEffects,
690 );
691
692 fn multi_insert_transaction_and_effects(
693 &self,
694 transactions_and_effects: &[VerifiedExecutionData],
695 );
696}
697
698pub trait TestingAPI: Send + Sync {
699 fn database_for_testing(&self) -> Arc<AuthorityStore>;
700
701 fn cache_for_testing(&self) -> &WritebackCache;
702}
703
704macro_rules! implement_storage_traits {
705 ($implementor: ident) => {
706 impl ObjectStore for $implementor {
707 fn get_object(&self, object_id: &ObjectID) -> Option<Object> {
708 ObjectCacheRead::get_object(self, object_id)
709 }
710
711 fn get_object_by_key(
712 &self,
713 object_id: &ObjectID,
714 version: sui_types::base_types::VersionNumber,
715 ) -> Option<Object> {
716 ObjectCacheRead::get_object_by_key(self, object_id, version)
717 }
718 }
719
720 impl RuntimeObjectResolver for $implementor {
721 fn read_child_object(
722 &self,
723 parent: &ObjectID,
724 child: &ObjectID,
725 child_version_upper_bound: SequenceNumber,
726 ) -> SuiResult<Option<Object>> {
727 let Some(child_object) =
728 self.find_object_lt_or_eq_version(*child, child_version_upper_bound)
729 else {
730 return Ok(None);
731 };
732
733 let parent = *parent;
734 if child_object.owner != Owner::ObjectOwner(parent.into()) {
735 return Err(SuiErrorKind::InvalidChildObjectAccess {
736 object: *child,
737 given_parent: parent,
738 actual_owner: child_object.owner.clone(),
739 }
740 .into());
741 }
742 Ok(Some(child_object))
743 }
744
745 fn get_object_received_at_version(
746 &self,
747 owner: &ObjectID,
748 receiving_object_id: &ObjectID,
749 receive_object_at_version: SequenceNumber,
750 epoch_id: EpochId,
751 ) -> SuiResult<Option<Object>> {
752 let Some(recv_object) = ObjectCacheRead::get_object_by_key(
753 self,
754 receiving_object_id,
755 receive_object_at_version,
756 ) else {
757 return Ok(None);
758 };
759
760 if recv_object.owner != Owner::AddressOwner((*owner).into())
766 || self.have_received_object_at_version(
767 FullObjectKey::new(
769 FullObjectID::new(*receiving_object_id, None),
770 receive_object_at_version,
771 ),
772 epoch_id,
773 )
774 {
775 return Ok(None);
776 }
777
778 Ok(Some(recv_object))
779 }
780 }
781
782 impl BackingPackageStore for $implementor {
783 fn get_package_object(
784 &self,
785 package_id: &ObjectID,
786 ) -> SuiResult<Option<PackageObject>> {
787 ObjectCacheRead::get_package_object(self, package_id)
788 }
789 }
790
791 impl ParentSync for $implementor {
792 fn get_latest_parent_entry_ref_deprecated(
793 &self,
794 object_id: ObjectID,
795 ) -> Option<ObjectRef> {
796 ObjectCacheRead::get_latest_object_ref_or_tombstone(self, object_id)
797 }
798 }
799 };
800}
801
802macro_rules! implement_passthrough_traits {
804 ($implementor: ident) => {
805 impl CheckpointCache for $implementor {
806 fn deprecated_get_transaction_checkpoint(
807 &self,
808 digest: &TransactionDigest,
809 ) -> Option<(EpochId, CheckpointSequenceNumber)> {
810 self.store
811 .deprecated_get_transaction_checkpoint(digest)
812 .expect("db error")
813 }
814
815 fn deprecated_multi_get_transaction_checkpoint(
816 &self,
817 digests: &[TransactionDigest],
818 ) -> Vec<Option<(EpochId, CheckpointSequenceNumber)>> {
819 self.store
820 .deprecated_multi_get_transaction_checkpoint(digests)
821 .expect("db error")
822 }
823
824 fn deprecated_insert_finalized_transactions(
825 &self,
826 digests: &[TransactionDigest],
827 epoch: EpochId,
828 sequence: CheckpointSequenceNumber,
829 ) {
830 self.store
831 .deprecated_insert_finalized_transactions(digests, epoch, sequence)
832 .expect("db error");
833 }
834 }
835
836 impl ExecutionCacheReconfigAPI for $implementor {
837 fn insert_genesis_object(&self, object: Object) {
838 self.insert_genesis_object_impl(object)
839 }
840
841 fn bulk_insert_genesis_objects(&self, objects: &[Object]) {
842 self.bulk_insert_genesis_objects_impl(objects)
843 }
844
845 fn set_epoch_start_configuration(&self, epoch_start_config: &EpochStartConfiguration) {
846 self.store
847 .set_epoch_start_configuration(epoch_start_config)
848 .expect("db error");
849 }
850
851 fn update_epoch_flags_metrics(&self, old: &[EpochFlag], new: &[EpochFlag]) {
852 self.store.update_epoch_flags_metrics(old, new)
853 }
854
855 fn clear_state_end_of_epoch(&self, execution_guard: &ExecutionLockWriteGuard<'_>) {
856 self.clear_state_end_of_epoch_impl(execution_guard)
857 }
858
859 fn expensive_check_sui_conservation(
860 &self,
861 old_epoch_store: &AuthorityPerEpochStore,
862 ) -> SuiResult {
863 self.store
864 .expensive_check_sui_conservation(self, old_epoch_store)
865 }
866
867 fn checkpoint_db(&self, path: &std::path::Path) -> SuiResult {
868 self.store.perpetual_tables.checkpoint_db(path)
869 }
870
871 fn maybe_reaccumulate_state_hash(
872 &self,
873 cur_epoch_store: &AuthorityPerEpochStore,
874 new_protocol_version: ProtocolVersion,
875 ) {
876 self.store
877 .maybe_reaccumulate_state_hash(cur_epoch_store, new_protocol_version)
878 }
879
880 fn reconfigure_cache<'a>(
881 &'a self,
882 _: &'a EpochStartConfiguration,
883 ) -> BoxFuture<'a, ()> {
884 std::future::ready(()).boxed()
888 }
889 }
890
891 impl TestingAPI for $implementor {
892 fn database_for_testing(&self) -> Arc<AuthorityStore> {
893 self.store.clone()
894 }
895
896 fn cache_for_testing(&self) -> &WritebackCache {
897 self
898 }
899 }
900 };
901}
902
903use implement_passthrough_traits;
904
905implement_storage_traits!(WritebackCache);
906
907pub trait ExecutionCacheAPI:
908 ObjectCacheRead
909 + ExecutionCacheWrite
910 + ExecutionCacheCommit
911 + ExecutionCacheReconfigAPI
912 + CheckpointCache
913 + StateSyncAPI
914{
915}